ProTable - Advanced Tables

ProTable was created to solve the problem of having to write a lot of sample code for tables in a project, so a lot of common logic was encapsulated in it. These wrappers can be simply categorized as pre-defined behaviors and pre-defined logic.

Thanks to ProForm's capabilities, ProForm can take many forms, switch between query form types, set up deformations to become a simple Form form, perform new creation, etc.

When to Use

When your forms need to interact with the server or need multiple cell styles, ProTable is the right choice.

Code Demo

Querying a table


Downgrade to a normal table

Lightweight filter replacement query form

Forms without ToolBar

Nested tables

Left and right structure

Batch manipulation of tables

Manipulating query forms with formRef

RTL (النسخة العربية)

RTL means right-to-left.

Controlled table settings columns

You can hide some columns by default, but in the action column you can select

Tables polling network data

Search form customization

When the built-in form items don't meet our basic needs, we need to customize the default components, which we can use with fieldProps and renderFormItem.

fieldProps can pass the props through and set the select style and multi-select issues.

renderFormItem does the rewriting logic, passing in item and props for rendering, but note that we have to assign value and onChange to the props, otherwise the form won't get the parameters.

renderFormItem: (_, { type, defaultRender, formItemProps, fieldProps, . .rest }, form) => {
if (type === 'form') {
return null;
const status = form.getFieldValue('state');
if (status ! == 'open') {
return <Input {... .fieldProps} placeholder="Please enter test" />;
return defaultRender(_);

The definition of renderFormItem, the exact value of which can be seen by opening the console.

renderFormItem?: (
item: ProColumns<T>,
config: {
value?: any;
onChange?: (value: any) => void;
onSelect?: (value: any) => void;
type: ProTableTypes;
defaultRender: (newItem: ProColumns<any>) => JSX.Element | null;
form: FormInstance,
) => JSX.Element | false | null;

Form action customization

Toolbar Customization

Configure toolbar rendering using the toolbar property extension.

Required Inquiry Form

Try to use initialValue to solve the problem, required fields are more frustrating

Form body customization

ProTable has built-in support for internationalization, and as a component with a relatively small amount of text, we can implement internationalization ourselves at a low cost.

Here is the full amount of text

const enLocale = {
tableForm: {
search: 'Query',
reset: 'Reset',
submit: 'Submit',
collapsed: 'Expand',
expand: 'Collapse',
inputPlaceholder: 'Please enter',
selectPlaceholder: 'Please select',
alert: {
clear: 'Clear',
tableToolBar: {
leftPin: 'Pin to left',
rightPin: 'Pin to right',
noPin: 'Unpinned',
leftFixedTitle: 'Fixed the left',
rightFixedTitle: 'Fixed the right',
noFixedTitle: 'Not Fixed',
reset: 'Reset',
columnDisplay: 'Column Display',
columnSetting: 'Settings',
fullScreen: 'Full Screen',
exitFullScreen: 'Exit Full Screen',
reload: 'Refresh',
density: 'Density',
densityDefault: 'Default',
densityLarger: 'Larger',
densityMiddle: 'Middle',
densitySmall: 'Compact',
// Generate the intl object
const enUSIntl = createIntl('en_US', enUS);
// use
<IntlProvider value={enUSIntl}>
<ProTable />

Value type examples

valueType - Date class

valueType - numeric class

valueType - Style Classes

valueType - Selection Classes


ProTable puts a layer of wrapping on top of antd's Table, supports some presets, and encapsulates some behaviors. Only api's that differ from antd Table are listed here.


request is the most important API of ProTable, request takes an object. The object must have data and success in it, and total is also required if manual paging is needed. request takes over the loading settings and re-executes them when the query form is queried and the params parameters are modified. Also the query form values and params parameters are brought in. The following is an example.

<ProTable<DataType, Params>
// params is a parameter that needs to be self-contained
// This parameter has higher priority and will override the parameters of the query form
request={async (
// The first parameter params is the combination of the query form and params parameters
// The first parameter will always have pageSize and current, which are antd specifications
params: T & {
pageSize: number;
current: number;
) => {
// Here you need to return a Promise, and you can transform the data before returning it
// If you need to transform the parameters you can change them here
const msg = await myQuery({
page: params.current,
pageSize: params.pageSize,
return {
data: msg.result,
// Please return true for success.
// otherwise the table will stop parsing the data, even if there is data
success: boolean,
// not passed will use the length of the data, if it is paged you must pass
total: number,


PropertyDescriptionTypeDefault Value
requestHow to get dataSource(params?: {pageSize,current},sort,filter) => {data,success,total}-
paramsAdditional parameters used for request query, once changed will trigger reloadingobject-
postDataProcess the data obtained through request(data: T[]) => T[]-
defaultDataDefault dataT[]-
actionRefReference to Table action for custom triggeringMutableRefObject<ActionType>-
formRefThe form instance of the query form can be obtained for some flexible configurationMutableRefObject<FormInstance>-
toolBarRenderRender toolbar, support returning a dom array, will automatically increase margin-right(action) => ReactNode[]-
onLoadTriggered after the data is loaded, it will be triggered multiple times(dataSource: T[]) => void-
onLoadingChangeTriggered when loading is modified, usually caused by network requests(loading:boolean)=>void-
onRequestErrorTriggered when data loading fails(error) => void-
tableClassNameclassName of the encapsulated tablestring-
tableStylestyle of the encapsulated tableCSSProperties-
optionstable toolbar, not displayed when set to false{{ fullScreen: boolean | function, reload: boolean | function,setting: true, density?: boolean }}{ fullScreen: false, reload :true, setting: true}
searchWhether to display the search form, when the object is passed in, it is the configuration of the search formfalse | [SearchConfig](#search-search form)-
dateFormatterConvert moment format data to a specific type, false will not be converted"string" | "number" | false"string"
defaultSizeDefault sizeSizeType-
beforeSearchSubmitMake some changes before searching(params:T)=>T-
onSizeChangeThe table size has changed(size:'default' |'middle' |'small') => void-
typepro-table type"form"-
formantd form configurationFormProps-
onSubmitTriggered when the form is submitted(params: U) => void-
onResetTriggered when the form is reset() => void-
columnEmptyTextDisplay when it is empty, display - when it is not set, false can turn off this functionstring | falsefalse
tableRenderCustom rendering table function(props,dom,domList:{ toolbar,alert,table}) => ReactNode-
toolbarTransparent transmission of ListToolBar configuration itemsListToolBarProps-
tableExtraRenderThe main function of the custom table(props: ProTableProps<T, U>, dataSource: T[]) => ReactNode;-
manualRequestDo you need to manually trigger the first request? When configured as true, the search form cannot be hiddenbooleanfalse
editableRelated configuration of editable table[TableRowEditable](/components/editable-table#editable-Editable row configuration)-
cardBorderedBorder of Card components around Table and Searchboolean | {search?: boolean, table?: boolean}false
debounceTimeDebounce timenumber10


PropertyDescriptionTypeDefault Value
recordThe row data to be added, generally contains a unique keyT{}
positionWhere does the line increase, start or endtop | bottombottom
(...buttonProps)ButtonProps of antdButtonProps


defaultValueThe default value of the column status, only for the first timerecord <string, columnState>;
ValueColumn status, support controlled modeRecord <string, columnState>;
ONCHANGEColumn status After changing(Value: Record <string, columnSstate>) => Viod
PersistenceKeyThe key of the persistence column is used to determine if it is the same tablestring | Number
PersistenceTypeThe type of persistence column, localStorage is also existing after closing the browser, sessionStorage closes the browser will be lostlocalstorage | sessionStorage

Search Search form

PropertyDescriptionTypeDefault Value
filterTypeFilter form type'query' | 'light''query'
searchTextSearch button textstringSearch
resetTextreset button textstringreset
submitTextThe text of the submit buttonstringSubmit
labelWidthLabel width'number' | 'auto'80
spanConfigure the number of columns in the query form'number' | 'ColConfig'defaultColConfig
classNameEncapsulated search Form classNamestring-
collapseRenderCollapse button render(collapsed: boolean,showCollapseButton?: boolean,) => ReactNode-
defaultCollapsedWhether to collapse by defaultbooleantrue
onCollapseCollapse button event(collapsed: boolean) => void;-
optionRenderCustom action bar((searchConfig,formProps,dom) => ReactNode[])|false-


const defaultColConfig = {
xs: 24,
sm: 24,
md: 12,
lg: 12,
xl: 8,
xxl: 6,
export type OptionsType =
| ((e: React.MouseEvent<HTMLSpanElement>, action?: ActionType) => void)
| boolean;
export type OptionConfig = {
density?: boolean;
fullScreen?: OptionsType;
reload?: OptionsType;
setting?: boolean;
search?: (SearchProps & { name?: string }) | boolean;

ActionRef manually triggered

Sometimes we need to manually trigger the reload of the table and other operations, we can use actionRef, the editable table also provides some operations to help us achieve our requirements faster.

interface ActionType {
reload: (resetPageIndex?: boolean) => void;
reloadAndRest: () => void;
reset: () => void;
clearSelected?: () => void;
startEditable: (rowKey: Key) => boolean;
cancelEditable: (rowKey: Key) => boolean;
const ref = useRef<ActionType>();
<ProTable actionRef={ref} />;
// refresh
// Refresh and clear, the page number will also be reset, excluding the form
// Reset to default values, including forms
// Clear the selected item
// start editing
// end editing

Columns column definition

Requesting remote data is more complicated, please see here for details.

| Property | Description | Type | Default Value | | --- | --- | --- | --- | --- | | title | Basically the same as in antd, but supports passing in a method | ReactNode \| ((config: ProColumnType<T>, type: ProTableTypes) => ReactNode) | - | | tooltip | An icon will be displayed after the title, and some information will be prompted after hover | string | - | | ellipsis | Whether to abbreviate automatically | boolean | - | | copyable | Whether to support copying | boolean | - | | valueEnum | The value enumeration will automatically convert the value as a key to retrieve the content to be displayed | valueEnum | - | | valueType | The type of value, which will generate different renderers | valueType | text | | order | The weight in the query form, the weight is ranked first | number | - | | fieldProps | The props of the query form will be transparently transmitted to the form item. If it is rendered as Input, all props of input are supported. Similarly, if it is select, all props of select are also supported. Also supports method input | (form,config)=>Record`\| `Record | - | | formItemProps | The configuration passed to Form.Item can be configured with rules, but the default query form rules does not take effect. Need to configure ignoreRules | (form,config)=>formItemProps | formItemProps | - | | renderText | Render like table, but must return string. If you just want to convert enumeration, you can use valueEnum | (text: any,record: T,index: number,action: UseFetchDataAction<T> ) => string | - | | render | Render similar to table, the first parameter becomes dom, and the fourth parameter action is added | (text: ReactNode,record: T,index: number,action: UseFetchDataAction<T>) => ReactNode \ | ReactNode[] | - | | renderFormItem | Render the input components of the query form | (item,{ type, defaultRender, formItemProps, fieldProps, },form) => ReactNode | - | | search | Configuration column search related, false is hidden | false | { transform: (value: any) => any } | true | | search.transform | The key of the conversion value, generally used for the conversion of the event interval | (value: any) => any | - | | editable | Whether it is editable in the edit table, the parameters of the function are the same as the render of the table | false | (text: any, record: T,index: number) => boolean | true | | colSize | The number of grids occupied by a form item, proportion = colSize*span, colSize defaults to 1, span is 8, span is form={{span:8}} global setting Of | number | - | | hideInSearch | Do not show this item in the query form | boolean | - | | hideInTable | Do not show this column in Table | boolean | - | | hideInForm | Do not show this column in Form | boolean | - | | hideInDescriptions | Do not show this column in Descriptions | boolean | - | | filters | The filter menu item in the header. When the value is true, valueEnum is automatically generated | boolean | object[] | false | | onFilter | Filter the form, use the built-in ProTable when it is true, turn off local filtering when it is false | (value, record) => boolean |'false' | false | | request | Request enumeration from server | request | - | | initialValue | Initial value of query form item | any | - |

valueType value type

ProTable encapsulates some commonly used value types to reduce repeated render operations. Configure a valueType to display formatted response data.

Batch operation

Like antd, batch operations need to be set to "rowSelection" to enable. Unlike antd, pro-table provides an alert to carry some information. You can customize it with tableAlertRender and tableAlertOptionRender. Set or return false to close.

PropertyDescriptionTypeDefault Value
alwaysShowAlertAlways show alert, no choice not to show by defaultboolean-
tableAlertRenderCustomize the information area on the left side of the batch operation toolbar, not displayed when false({ selectedRowKeys: Key[], selectedRows: T[], onCleanSelected: ()=>void }) => ReactNode)| false-
tableAlertOptionRenderCustomize the option area on the right side of the bulk operation toolbar, not displayed when false({ selectedRowKeys: Key[], selectedRows: T[], onCleanSelected: ()=>void }) => ReactNode)| false-

Searching for forms

ProTable will generate a Form for filtering list data based on columns, and the final value will be returned based on the first parameter via request, which looks like.

<ProTable request={(params,sort,filter)=>{ all params}}>

As per the specification, table forms do not require any mandatory parameters, and all clicks on search and reset will trigger a request to initiate a query.

Form's columns are generated with different types based on valueType.

Columns with a valueType of index indexBorder option and no dataIndex and key will be ignored.


Toolbar section for customizing forms.

Code Demo


Toolbar configuration properties for lists and tables

searchquery areaReactNode | SearchProps-
actionsactions areaReactNode[]-
settingssettings area(ReactNode | Setting)[]-
filterThe filter area, usually used with LightFilterReactNode-
multipleLineWhether to display multiple linesbooleanfalse
menumenu configurationListToolBarMenu-
tabsTabs configuration, only valid if multipleLine is trueListToolBarTabs-

SearchProps is a property of antd's Input.Search.


tooltiptooltip Descriptionstring-
keyoperation unique identifierstring-
onClickset to be triggered(key: string)=>void-


typetypeinline | dropdown | tabdropdown
activeKeycurrent valuestring-
itemsmenu items{ key: string; label: ReactNode }[]-
onChangeCallback for switching menus(activeKey)=>void-


activeKeycurrently selected itemstring-
itemsmenu items{ key: string; tab: ReactNode }[]-
onChangeCallback for toggling menu items(activeKey)=>void-