Don't use index as row key. (#4185)

* Ensure warning if key is undefined.

* Ensure getRecordKey receives index

* Remove rowKey's second parameter from doc.
This commit is contained in:
Wei Zhu 2016-12-16 17:53:08 +08:00 committed by 偏右
parent ba0dce98f5
commit d7a110552b
4 changed files with 15 additions and 17 deletions

View File

@ -5,7 +5,7 @@ import { Store } from './createStore';
export interface SelectionCheckboxAllProps { export interface SelectionCheckboxAllProps {
store: Store; store: Store;
disabled: boolean; disabled: boolean;
getCheckboxPropsByItem: (item) => any; getCheckboxPropsByItem: (item, index) => any;
getRecordKey: (record, index?) => string; getRecordKey: (record, index?) => string;
data: any[]; data: any[];
onChange: (e) => void; onChange: (e) => void;
@ -50,7 +50,7 @@ export default class SelectionCheckboxAll extends React.Component<SelectionCheck
if (type === 'every' || type === 'some') { if (type === 'every' || type === 'some') {
return ( return (
byDefaultChecked byDefaultChecked
? data[type](item => getCheckboxPropsByItem(item).defaultChecked) ? data[type]((item, i) => getCheckboxPropsByItem(item, i).defaultChecked)
: data[type]((item, i) => : data[type]((item, i) =>
store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0) store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0)
); );

View File

@ -156,12 +156,12 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
}); });
} }
getCheckboxPropsByItem = (item) => { getCheckboxPropsByItem = (item, index) => {
const { rowSelection = {} } = this.props; const { rowSelection = {} } = this.props;
if (!rowSelection.getCheckboxProps) { if (!rowSelection.getCheckboxProps) {
return {}; return {};
} }
const key = this.getRecordKey(item); const key = this.getRecordKey(item, index);
// Cache checkboxProps // Cache checkboxProps
if (!this.CheckboxPropsCache[key]) { if (!this.CheckboxPropsCache[key]) {
this.CheckboxPropsCache[key] = rowSelection.getCheckboxProps(item); this.CheckboxPropsCache[key] = rowSelection.getCheckboxProps(item);
@ -175,7 +175,7 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
return []; return [];
} }
return this.getFlatData() return this.getFlatData()
.filter(item => this.getCheckboxPropsByItem(item).defaultChecked) .filter((item, rowIndex) => this.getCheckboxPropsByItem(item, rowIndex).defaultChecked)
.map((record, rowIndex) => this.getRecordKey(record, rowIndex)); .map((record, rowIndex) => this.getRecordKey(record, rowIndex));
} }
@ -465,7 +465,7 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection(); const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection); const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const changableRowKeys = data const changableRowKeys = data
.filter(item => !this.getCheckboxPropsByItem(item).disabled) .filter((item, i) => !this.getCheckboxPropsByItem(item, i).disabled)
.map((item, i) => this.getRecordKey(item, i)); .map((item, i) => this.getRecordKey(item, i));
// 记录变化的列 // 记录变化的列
@ -532,7 +532,7 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
renderSelectionBox = (type) => { renderSelectionBox = (type) => {
return (_, record, index) => { return (_, record, index) => {
let rowIndex = this.getRecordKey(record, index); // 从 1 开始 let rowIndex = this.getRecordKey(record, index); // 从 1 开始
const props = this.getCheckboxPropsByItem(record); const props = this.getCheckboxPropsByItem(record, index);
const handleChange = (e) => { const handleChange = (e) => {
type === 'radio' ? this.handleRadioSelect(record, rowIndex, e) : type === 'radio' ? this.handleRadioSelect(record, rowIndex, e) :
this.handleSelect(record, rowIndex, e); this.handleSelect(record, rowIndex, e);
@ -553,12 +553,10 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
}; };
} }
getRecordKey = (record, index?): string => { getRecordKey = (record, index): string => {
const rowKey = this.props.rowKey; const rowKey = this.props.rowKey;
if (typeof rowKey === 'function') { const recordKey = (typeof rowKey === 'function') ?
return rowKey(record, index); rowKey(record, index) : record[rowKey as string];
}
let recordKey = record[rowKey as string] !== undefined ? record[rowKey as string] : index;
warning(recordKey !== undefined, warning(recordKey !== undefined,
'Each record in table should have a unique `key` prop, or set `rowKey` to an unique primary key.' 'Each record in table should have a unique `key` prop, or set `rowKey` to an unique primary key.'
); );
@ -569,9 +567,9 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
const { prefixCls, rowSelection } = this.props; const { prefixCls, rowSelection } = this.props;
const columns = this.columns.concat(); const columns = this.columns.concat();
if (rowSelection) { if (rowSelection) {
const data = this.getFlatCurrentPageData().filter((item) => { const data = this.getFlatCurrentPageData().filter((item, index) => {
if (rowSelection.getCheckboxProps) { if (rowSelection.getCheckboxProps) {
return !this.getCheckboxPropsByItem(item).disabled; return !this.getCheckboxPropsByItem(item, index).disabled;
} }
return true; return true;
}); });
@ -581,7 +579,7 @@ export default class Table<T> extends React.Component<TableProps<T>, any> {
className: `${prefixCls}-selection-column`, className: `${prefixCls}-selection-column`,
}; };
if (rowSelection.type !== 'radio') { if (rowSelection.type !== 'radio') {
const checkboxAllDisabled = data.every(item => this.getCheckboxPropsByItem(item).disabled); const checkboxAllDisabled = data.every((item, index) => this.getCheckboxPropsByItem(item, index).disabled);
selectionColumn.title = ( selectionColumn.title = (
<SelectionCheckboxAll <SelectionCheckboxAll
store={this.store} store={this.store}

View File

@ -57,7 +57,7 @@ const columns = [{
| size | size of table: `default` or `small` | String | `default` | | size | size of table: `default` or `small` | String | `default` |
| dataSource | data record array to be rendered | Array | | | dataSource | data record array to be rendered | Array | |
| columns | columns of table | Array | - | | columns | columns of table | Array | - |
| rowKey | get row's key, could be a string or function | String or Function(record, index):string | 'key' | | rowKey | get row's key, could be a string or function | String or Function(record):string | 'key' |
| rowClassName | get row's className | Function(record, index):string | - | | rowClassName | get row's className | Function(record, index):string | - |
| expandedRowRender | expanded container render for each row | Function | - | | expandedRowRender | expanded container render for each row | Function | - |
| defaultExpandedRowKeys | initial expanded row keys | Array | - | | defaultExpandedRowKeys | initial expanded row keys | Array | - |

View File

@ -58,7 +58,7 @@ const columns = [{
| size | 正常或迷你类型,`default` or `small` | String | default | | size | 正常或迷你类型,`default` or `small` | String | default |
| dataSource | 数据数组 | Array | | | dataSource | 数据数组 | Array | |
| columns | 表格列的配置描述,具体项见下表 | Array | - | | columns | 表格列的配置描述,具体项见下表 | Array | - |
| rowKey | 表格行 key 的取值,可以是字符串或一个函数 | String or Function(record, index):string | 'key' | | rowKey | 表格行 key 的取值,可以是字符串或一个函数 | String or Function(record):string | 'key' |
| rowClassName | 表格行的类名 | Function(record, index):string | - | | rowClassName | 表格行的类名 | Function(record, index):string | - |
| expandedRowRender | 额外的展开行 | Function | - | | expandedRowRender | 额外的展开行 | Function | - |
| defaultExpandedRowKeys | 默认展开的行 | Array | - | | defaultExpandedRowKeys | 默认展开的行 | Array | - |