diff --git a/content/show/table/index-en-US.md b/content/show/table/index-en-US.md index ae97f1d677..1bdfcb0d28 100644 --- a/content/show/table/index-en-US.md +++ b/content/show/table/index-en-US.md @@ -257,7 +257,10 @@ This feature can be turned on by passing in `rowSelection`. - Click the selection box in the header, and all rows in the `dataSource` that are not in the state of `disabled` will be selected. The callback function for selecting all rows is `onSelectAll`; - Clicking on the row selection box will select the current row. Its callback function is `onSelect`; -> Note: Be sure to provide a "key" for each row of data that is different from other row values, or use the rowKey parameter to specify a property name as the primary key. + +
1. Be sure to provide a "key" for each row of data that is different from other row values, or use the rowKey parameter to specify a property name as the primary key.
+
2. If you encounter the problem of returning to the first page after clicking a row selection on the second page, please check whether component rendering triggers "dataSource" update (shallow equal). After the "dataSource" is updated, the uncontrolled page turner will return to the first page. Please put "dataSource" inside state.
+
```jsx live=true noInline=true dir="column" import React from 'react'; @@ -265,7 +268,8 @@ import { Table, Avatar } from '@douyinfe/semi-ui'; import { IconMore } from '@douyinfe/semi-icons'; function App() { - const columns = [ + const [selectedKeys, setSelectedKeys] = useState([]); + const columns = useMemo(() => [ { title: 'Title', dataIndex: 'name', @@ -313,8 +317,8 @@ function App() { return ; }, }, - ]; - const data = [ + ], []); + const data = useMemo(() => [ { key: '1', name: 'Semi Design design draft.fig', @@ -369,7 +373,7 @@ function App() { updateTime: '2020-01-26 11:01', avatarBg: 'light-blue', }, - ]; + ], []); const rowSelection = { getCheckboxProps: record => ({ disabled: record.name === 'Design docs', // Column configuration not to be checked @@ -383,6 +387,7 @@ function App() { }, onChange: (selectedRowKeys, selectedRows) => { console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); + setSelectedKeys(selectedRowKeys); }, }; @@ -1080,6 +1085,8 @@ Filters and sorting controls are integrated inside the table, and users can pass > Note: Be sure to provide a "key" for each row of data that is different from other row values, or use the rowKey parameter to specify a property name as the primary key. +> Note: Sorting and filtering columns must set independent "dataIndex" + ```jsx live=true noInline=true dir="column" import React, { useState, useMemo } from 'react'; import { Table, Avatar } from '@douyinfe/semi-ui'; @@ -5266,7 +5273,7 @@ render(App); | clickGroupedRowToExpand | Group content expands or collapses when the group header row is clicked | boolean | | **0.29.0** | | columns | For a configuration description of the table column, see [Column](#Column) | Column [] | [] | | components | Override the elements of Table, such as table, body, row, td, th, etc. | TableComponents | | -| dataSource | Data, Each item needs to have a key, or specify rowKey, see the beginning of the document | RecordType[] | [] | +| dataSource | Data. **An independent key of each data record is need, or use rowKey to specify an attribute name as the primary key** | RecordType[] | [] | | defaultExpandAllRows | All rows are expanded by default | boolean | false | | defaultExpandAllGroupRows | All grouped rows are expanded by default | boolean | false | **1.30.0** | | defaultExpandedRowKeys | Default expansion of row key array | Array <\*> | [] | @@ -5274,7 +5281,7 @@ render(App); | expandCellFixed | Whether the column of the expansion icon is fixed or not, the same value as the fixed value in Column | boolean\|string | false | | expandIcon | Custom expansion icon, hidden when it is `false` | boolean
\|ReactNode
\| (expanded: boolean) => ReactNode | | | expandedRowKeys | Expanded rows, the row expansion function will be controlled when this parameter is introduced. | (string \| number)[] | | -| expandedRowRender | Extra unfolding lines | (record: object, index: number, expanded: boolean) => ReactNode | | +| expandedRowRender | Extra unfolding lines. **An independent key of each data record is need** | (record: object, index: number, expanded: boolean) => ReactNode | | | expandAllRows | All rows are expanded | boolean | false | **1.30.0** | | expandAllGroupRows | All grouped rows are expanded | boolean | false | **1.30.0** | | expandRowByClick | Expand row when click row | boolean | false | **1.31.0** | @@ -5437,13 +5444,13 @@ import { Table } from '@douyinfe/semi-ui'; | resize | Whether to enable resize mode, this property will take effect only after Table resizable is enabled | boolean | | **2.42.0** | | sortChildrenRecord | Whether to sort child data locally | boolean | | **0.29.0** | | sortOrder | The controlled property of the sorting, the sorting of this control column can be set to 'ascend'\|'descended '\|false | boolean | false | -| sorter | Sorting function, local sorting uses a function (refer to the compareFunction of Array.sort), requiring a server-side sorting can be set to true | boolean\|(r1: RecordType, r2: RecordType, sortOrder: 'ascend' \| 'descend') => number | true | +| sorter | Sorting function, local sorting uses a function (refer to the compareFunction of Array.sort), requiring a server-side sorting can be set to true. **An independent dataIndex must be set for the sort column, and an independent key must be set for each data item in the dataSource** | boolean\|(r1: RecordType, r2: RecordType, sortOrder: 'ascend' \| 'descend') => number | true | | sortIcon |Customize the sort icon. The returned node controls the entire sort button, including ascending and descending buttons. Need to control highlighting behavior based on sortOrder | (props: { sortOrder }) => ReactNode | | **2.50.0** | | title | Column header displays text. When a function is passed in, title will use the return value of the function; when other types are passed in, they will be aggregated with sorter and filter. It needs to be used with useFullRender to obtain parameters such as filter in the function type | string \| ReactNode\|({ filter: ReactNode, sorter: ReactNode, selection: ReactNode }) => ReactNode. | | Function type requires **0.34.0** | | useFullRender | Whether to completely customize the rendering, see [Full Custom Rendering](#Fully-custom-rendering) for usage details, enabling this feature will cause a certain performance loss | boolean | false | **0.34.0** | | width | Column width | string \| number | | | onCell | Set cell properties | (record: RecordType, rowIndex: number) => object | | -| onFilter | Determine the running function of the filter in local mode | (filteredValue: any, record: RecordType) => boolean | | +| onFilter | Determine the running function of the filter in local mode. **An independent dataIndex must be set for the filter column, and an independent key must be set for each data item in the dataSource** | (filteredValue: any, record: RecordType) => boolean | | | onFilterDropdownVisibleChange | A callback when a custom filter menu is visible | (visible: boolean) => void | | | onHeaderCell | Set the head cell property | (column: RecordType, columnIndex: number) => object | | @@ -5586,6 +5593,39 @@ function Demo() { ## FAQ +- **Clicking the row selection button on the second page will jump to the first page? ** + + After the Table's dataSource is updated, the page number will be reset to the initial state. Please check if the data source changed when the component was rendered. + + ```typescript + function App() { + const [dataSource, setDataSource] = useState([]); + + useEffect(() => { + // ✅ Correct + const getData = () => { + // fetch data + const newData = fetch(/**/); + // set data + setDataSource(dataSource); + }; + + getData(); + }, []); + + // ❌ Error + const data = []; + + return ; + } + ``` + +- **The number of filtered data is wrong?** + + Please check that your filter columns and data sources are configured correctly. + + The filter column needs to set an independent `dataIndex`, and the dataSource needs to set an independent `key`. Please refer to the `dataSource` API. Otherwise the filtering function will not work properly. + - **Why is the table data not updated?** At present, all parameters of the table component are shallow comparison. That is to say, if the parameter value type is an array or object, you need to manually change its reference to trigger the update. Similarly, if you don't want to trigger additional updates, try not to use literal values when passing parameters directly or define reference parameter values in the render process: diff --git a/content/show/table/index.md b/content/show/table/index.md index e5d964e514..c26f861af4 100644 --- a/content/show/table/index.md +++ b/content/show/table/index.md @@ -257,17 +257,19 @@ render(App); - 点击行的选择框会选中当前行。它的回调函数为 `onSelect`; - 请务必为 dataSource 中每行数据提供一个与其他行值不同的 `key`,或者使用 `rowKey` 参数指定一个作为主键的属性名。 +
1. 请务必为 `dataSource` 中每行数据提供一个与其他行值不同的 `key`,或者使用 `rowKey` 参数指定一个作为主键的属性名。
+
2. 如你遇见在第二页点击行选择后,回到第一页问题,请检查组件渲染是否触发了 `dataSource` 更新(浅对比)。`dataSource` 更新后,非受控的翻页器会回到第一页。请将 `dataSource` 放在 state 内。
- ```jsx live=true noInline=true dir="column" import React from 'react'; import { Table, Avatar } from '@douyinfe/semi-ui'; import { IconMore } from '@douyinfe/semi-icons'; function App() { - const columns = [ + const [selectedKeys, setSelectedKeys] = useState([]); + + const columns = useMemo(() => [ { title: '标题', dataIndex: 'name', @@ -315,8 +317,9 @@ function App() { return ; }, }, - ]; - const data = [ + ], []); + + const data = useMemo(() => [ { key: '1', name: 'Semi Design 设计稿.fig', @@ -371,7 +374,8 @@ function App() { updateTime: '2020-01-26 11:01', avatarBg: 'light-blue', }, - ]; + ], []); + const rowSelection = { getCheckboxProps: record => ({ disabled: record.name === '设计文档', // Column configuration not to be checked @@ -385,6 +389,7 @@ function App() { }, onChange: (selectedRowKeys, selectedRows) => { console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); + setSelectedKeys(selectedRowKeys); }, }; @@ -1083,7 +1088,8 @@ render(App); 表格内部集成了过滤器和排序控件,用户可以通过在 Column 中传入 `filters` 以及 `onFilter` 开启表头的过滤器控件展示,传入 `sorter` 开启表头的排序控件的展示。 - 请为 `dataSource` 中的每个数据项提供一个与其他数据项值不同的 `key`,或者使用 `rowKey` 参数指定一个作为主键的属性名,表格的行选择、展开等绝大多数行操作功能都会使用到。 +
1. 请为 `dataSource` 中的每个数据项提供一个与其他数据项值不同的 `key`,或者使用 `rowKey` 参数指定一个作为主键的属性名,表格的行选择、展开等绝大多数行操作功能都会使用到。
+
2. 排序和筛选列必须设置独立的 `dataIndex`
```jsx live=true noInline=true dir="column" @@ -5273,7 +5279,7 @@ render(App); | clickGroupedRowToExpand | 点击分组表头行时分组内容展开或收起 | boolean | | **0.29.0** | | columns | 表格列的配置描述,详见[Column](#Column) | Column[] | [] | | components | 覆盖 Table 的组成元素,如 table, body,row,td,th 等 | TableComponents | | -| dataSource | 数据, 每项需要有key,或者指定 rowKey,见文档开头 | RecordType[] | [] | +| dataSource | 数据。**请为每一条数据分配一个独立的 key,或使用 rowKey 指定一个作为主键的属性名** | RecordType[] | [] | | defaultExpandAllRows | 默认是否展开所有行,动态加载数据时不生效 | boolean | false | | defaultExpandAllGroupRows | 默认是否展开分组行,动态加载数据时不生效 | boolean | false | **1.30.0** | | defaultExpandedRowKeys | 默认展开的行 key 数组,,动态加载数据时不生效 | Array<\*> | [] | @@ -5282,7 +5288,7 @@ render(App); | expandCellFixed | 展开图标所在列是否固定,与 Column 中的 fixed 取值相同 | boolean\|string | false | | expandIcon | 自定义展开按钮,传 `false` 关闭默认的渲染 | boolean \| ReactNode
\| (expanded: boolean) => ReactNode | | | expandedRowKeys | 展开的行,传入此参数时行展开功能将受控 | (string \| number)[] | | -| expandedRowRender | 额外的展开行 | (record: object, index: number, expanded: boolean) => ReactNode | | +| expandedRowRender | 额外的展开行。**请为每一条数据分配一个独立的 key,或使用 rowKey 指定一个作为主键的属性名** | (record: object, index: number, expanded: boolean) => ReactNode | | | expandAllRows | 是否展开所有行 | boolean | false | **1.30.0** | | expandAllGroupRows | 是否展开分组行 | boolean | false | **1.30.0** | | expandRowByClick | 点击行时是否展开可展开行 | boolean | false | **1.31.0** | @@ -5431,7 +5437,7 @@ import { Table } from '@douyinfe/semi-ui'; | className | 列样式名 | string | | | children | 表头合并时用于子列的设置 | Column[] | | | colSpan | 表头列合并,设置为 0 时,不渲染 | number | | -| dataIndex | 列数据在数据项中对应的 key,使用排序或筛选时必传 | string | | +| dataIndex | 列数据在数据项中对应的 key,使用排序或筛选时必传,且需要保持不重复 | string | | | defaultFilteredValue | 筛选的默认值,值为已筛选的 value 数组 | any[] | | **2.5.0** | | defaultSortOrder | 排序的默认值,可设置为 'ascend'\|'descend'\|false | boolean\| string | false | **1.31.0** | | ellipsis | 文本缩略,开启后 table-layout 会自动切换为 fixed | boolean\| { showTitle: boolean } | false | **2.34.0** | @@ -5442,7 +5448,7 @@ import { Table } from '@douyinfe/semi-ui'; | filterIcon | 自定义 filter 图标 | boolean\|ReactNode\|(filtered: boolean) => ReactNode | | | filterMultiple | 是否多选 | boolean | true | | filteredValue | 筛选的受控属性,外界可用此控制列的筛选状态,值为已筛选的 value 数组 | any[] | | -| filters | 表头的筛选菜单项 | Filter[] | | +| filters | 表头的筛选菜单项。 | Filter[] | | | fixed | 列是否固定,可选 true(等效于 left) 'left' 'right',在 RTL 时会自动切换 | boolean\|string | false | | key | React 需要的 key,如果已经设置了唯一的 dataIndex,可以忽略这个属性 | string | | | render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并 | (text: any, record: RecordType, index: number, { expandIcon?: ReactNode, selection?: ReactNode, indentText?: ReactNode }) => object\|ReactNode | | @@ -5451,13 +5457,13 @@ import { Table } from '@douyinfe/semi-ui'; | resize | 是否开启 resize 模式,只有 Table resizable 开启后此属性才会生效 | boolean | | **2.42.0** | | sortChildrenRecord | 是否对子级数据进行本地排序 | boolean | | **0.29.0** | | sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 'ascend'\|'descend'\|false | boolean\| string | false | -| sorter | 排序函数,本地排序使用一个函数(参考 Array.sort 的 compareFunction),需要服务端排序可设为 true | boolean\|(r1: RecordType, r2: RecordType, sortOrder: 'ascend' \| 'descend') => number | true | +| sorter | 排序函数,本地排序使用一个函数(参考 Array.sort 的 compareFunction),需要服务端排序可设为 true。**必须给排序列设置一个独立的 dataIndex,必须为 dataSource 里面的每条数据项设置独立的 key** | boolean\|(r1: RecordType, r2: RecordType, sortOrder: 'ascend' \| 'descend') => number | true | | sortIcon | 自定义 sort 图标,返回的节点控制了整个排序按钮,包含升序和降序。需根据 sortOrder 控制高亮行为 | (props: { sortOrder }) => ReactNode | | **2.50.0** | | title | 列头显示文字。传入 function 时,title 将使用函数的返回值;传入其他类型,将会和 sorter、filter 进行聚合。需要搭配 useFullRender 获取函数类型中的 filter 等参数 | ReactNode\|({ filter: ReactNode, sorter: ReactNode, selection: ReactNode }) => ReactNode | | Function 类型需要**0.34.0** | | useFullRender | 是否完全自定义渲染,用法详见[完全自定义渲染](#完全自定义渲染), 开启此功能会造成一定的性能损耗 | boolean | false | **0.34.0** | | width | 列宽度 | string \| number | | | onCell | 设置单元格属性 | (record: RecordType, rowIndex: number) => object | | -| onFilter | 本地模式下,确定筛选的运行函数 | (filteredValue: any, record: RecordType) => boolean | | +| onFilter | 本地模式下,确定筛选的运行函数。**必须给筛选列设置一个独立的 dataIndex,必须为 dataSource 里面的每条数据项设置独立的 key** | (filteredValue: any, record: RecordType) => boolean | | | onFilterDropdownVisibleChange | 自定义筛选菜单可见变化时回调 | (visible: boolean) => void | | | onHeaderCell | 设置头部单元格属性 | (column: RecordType, columnIndex: number) => object | | @@ -5602,6 +5608,39 @@ function Demo() { ## FAQ +- **点击第二页的行选择按钮,会跳转到第一页?** + + Table 的 dataSource 更新后,会将页码重置到初始态。请检查数据源是否在组件渲染时发生了变化。 + + ```typescript + function App() { + const [dataSource, setDataSource] = useState([]); + + useEffect(() => { + // ✅ 正确 + const getData = () => { + // fetch data + const newData = fetch(/**/); + // set data + setDataSource(dataSource); + }; + + getData(); + }, []); + + // ❌ 错误 + const data = []; + + return
; + } + ``` + +- **筛选后的数据条数不对?** + + 请检查你的筛选列和数据源是否配置正确。 + + 筛选列需设置独立的 dataIndex,同时 dataSource 需要设置独立的 key,请参考 dataSource API。否则筛选功能无法正常工作。 + - **表格数据为何没有更新?** Table 组件目前所有参数都为浅层对比,也就是说如果该参数值类型为一个 Array 或者 Object,你需要手动改变其引用才能触发更新。同理,如果你不想触发额外更新,尽量不要直接在传参的时候使用字面量或是在 render 过程中定义引用型参数值: