mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
fix(Table): move rowSelection logic to getDerivedStateFromProps
This commit is contained in:
parent
8a60e19b8e
commit
948d0bd7bb
@ -33,6 +33,8 @@ import {
|
|||||||
PaginationConfig,
|
PaginationConfig,
|
||||||
PrepareParamsArgumentsReturn,
|
PrepareParamsArgumentsReturn,
|
||||||
ExpandIconProps,
|
ExpandIconProps,
|
||||||
|
WithStore,
|
||||||
|
CheckboxPropsCache,
|
||||||
} from './interface';
|
} from './interface';
|
||||||
import Pagination from '../pagination';
|
import Pagination from '../pagination';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
@ -104,7 +106,7 @@ const createComponents = (components: TableComponents = {}, prevComponents?: Tab
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
class Table<T> extends React.Component<TableProps<T>, TableState<T>> {
|
||||||
static Column = Column;
|
static Column = Column;
|
||||||
|
|
||||||
static ColumnGroup = ColumnGroup;
|
static ColumnGroup = ColumnGroup;
|
||||||
@ -164,6 +166,23 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nextProps.rowSelection && 'selectedRowKeys' in nextProps.rowSelection) {
|
||||||
|
nextProps.store.setState({
|
||||||
|
selectedRowKeys: nextProps.rowSelection.selectedRowKeys || [],
|
||||||
|
});
|
||||||
|
} else if (prevProps.rowSelection && !nextProps.rowSelection) {
|
||||||
|
nextProps.store.setState({
|
||||||
|
selectedRowKeys: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if ('dataSource' in nextProps && nextProps.dataSource !== prevProps.dataSource) {
|
||||||
|
nextProps.store.setState({
|
||||||
|
selectionDirty: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// https://github.com/ant-design/ant-design/issues/10133
|
||||||
|
nextProps.setCheckboxPropsCache({});
|
||||||
|
|
||||||
if (nextProps.components !== prevProps.components) {
|
if (nextProps.components !== prevProps.components) {
|
||||||
const components = createComponents(nextProps.components, prevProps.components);
|
const components = createComponents(nextProps.components, prevProps.components);
|
||||||
|
|
||||||
@ -176,12 +195,6 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
return nextState;
|
return nextState;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckboxPropsCache: {
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
store: Store;
|
|
||||||
|
|
||||||
columns: ColumnProps<T>[];
|
columns: ColumnProps<T>[];
|
||||||
|
|
||||||
components: TableComponents;
|
components: TableComponents;
|
||||||
@ -222,38 +235,13 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
prevProps: props,
|
prevProps: props,
|
||||||
components: createComponents(props.components),
|
components: createComponents(props.components),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.CheckboxPropsCache = {};
|
|
||||||
|
|
||||||
this.store = createStore({
|
|
||||||
selectedRowKeys: getRowSelection(props).selectedRowKeys || [],
|
|
||||||
selectionDirty: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Readonly<TableProps<T>>) {
|
componentDidUpdate() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
|
|
||||||
this.columns = props.columns || normalizeColumns(props.children as React.ReactChildren);
|
this.columns = props.columns || normalizeColumns(props.children as React.ReactChildren);
|
||||||
|
|
||||||
if (props.rowSelection && 'selectedRowKeys' in props.rowSelection) {
|
|
||||||
this.store.setState({
|
|
||||||
selectedRowKeys: props.rowSelection.selectedRowKeys || [],
|
|
||||||
});
|
|
||||||
} else if (prevProps.rowSelection && !props.rowSelection) {
|
|
||||||
this.store.setState({
|
|
||||||
selectedRowKeys: [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if ('dataSource' in props && props.dataSource !== prevProps.dataSource) {
|
|
||||||
this.store.setState({
|
|
||||||
selectionDirty: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/10133
|
|
||||||
this.CheckboxPropsCache = {};
|
|
||||||
|
|
||||||
if (this.getSortOrderColumns(this.columns).length > 0) {
|
if (this.getSortOrderColumns(this.columns).length > 0) {
|
||||||
const sortState = this.getSortStateFromColumns(this.columns);
|
const sortState = this.getSortStateFromColumns(this.columns);
|
||||||
if (
|
if (
|
||||||
@ -284,16 +272,16 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
}
|
}
|
||||||
const key = this.getRecordKey(item, index);
|
const key = this.getRecordKey(item, index);
|
||||||
// Cache checkboxProps
|
// Cache checkboxProps
|
||||||
if (!this.CheckboxPropsCache[key]) {
|
if (!this.props.checkboxPropsCache[key]) {
|
||||||
this.CheckboxPropsCache[key] = rowSelection.getCheckboxProps(item) || {};
|
this.props.checkboxPropsCache[key] = rowSelection.getCheckboxProps(item) || {};
|
||||||
const checkboxProps = this.CheckboxPropsCache[key];
|
const checkboxProps = this.props.checkboxPropsCache[key];
|
||||||
warning(
|
warning(
|
||||||
!('checked' in checkboxProps) && !('defaultChecked' in checkboxProps),
|
!('checked' in checkboxProps) && !('defaultChecked' in checkboxProps),
|
||||||
'Table',
|
'Table',
|
||||||
'Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.',
|
'Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return this.CheckboxPropsCache[key];
|
return this.props.checkboxPropsCache[key];
|
||||||
};
|
};
|
||||||
|
|
||||||
getDefaultSelection() {
|
getDefaultSelection() {
|
||||||
@ -502,7 +490,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
return {
|
return {
|
||||||
...custom,
|
...custom,
|
||||||
prefixCls,
|
prefixCls,
|
||||||
store: this.store,
|
store: this.props.store,
|
||||||
rowKey: this.getRecordKey(record, index),
|
rowKey: this.getRecordKey(record, index),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -511,7 +499,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
const { selectWay, record, checked, changeRowKeys, nativeEvent } = selectionInfo;
|
const { selectWay, record, checked, changeRowKeys, nativeEvent } = selectionInfo;
|
||||||
const rowSelection = getRowSelection(this.props);
|
const rowSelection = getRowSelection(this.props);
|
||||||
if (rowSelection && !('selectedRowKeys' in rowSelection)) {
|
if (rowSelection && !('selectedRowKeys' in rowSelection)) {
|
||||||
this.store.setState({ selectedRowKeys });
|
this.props.store.setState({ selectedRowKeys });
|
||||||
}
|
}
|
||||||
const data = this.getFlatData();
|
const data = this.getFlatData();
|
||||||
if (!rowSelection.onChange && !rowSelection[selectWay]) {
|
if (!rowSelection.onChange && !rowSelection[selectWay]) {
|
||||||
@ -611,7 +599,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
|
|
||||||
this.setState(newState, () => {
|
this.setState(newState, () => {
|
||||||
this.scrollToFirstRow();
|
this.scrollToFirstRow();
|
||||||
this.store.setState({
|
this.props.store.setState({
|
||||||
selectionDirty: false,
|
selectionDirty: false,
|
||||||
});
|
});
|
||||||
const { onChange } = this.props;
|
const { onChange } = this.props;
|
||||||
@ -632,8 +620,10 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
handleSelect = (record: T, rowIndex: number, e: CheckboxChangeEvent) => {
|
handleSelect = (record: T, rowIndex: number, e: CheckboxChangeEvent) => {
|
||||||
const checked = e.target.checked;
|
const checked = e.target.checked;
|
||||||
const nativeEvent = e.nativeEvent;
|
const nativeEvent = e.nativeEvent;
|
||||||
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
|
const defaultSelection = this.props.store.getState().selectionDirty
|
||||||
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
|
? []
|
||||||
|
: this.getDefaultSelection();
|
||||||
|
let selectedRowKeys = this.props.store.getState().selectedRowKeys.concat(defaultSelection);
|
||||||
const key = this.getRecordKey(record, rowIndex);
|
const key = this.getRecordKey(record, rowIndex);
|
||||||
const { pivot } = this.state;
|
const { pivot } = this.state;
|
||||||
const rows = this.getFlatCurrentPageData();
|
const rows = this.getFlatCurrentPageData();
|
||||||
@ -667,7 +657,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ pivot: realIndex });
|
this.setState({ pivot: realIndex });
|
||||||
this.store.setState({
|
this.props.store.setState({
|
||||||
selectionDirty: true,
|
selectionDirty: true,
|
||||||
});
|
});
|
||||||
this.setSelectedRowKeys(selectedRowKeys, {
|
this.setSelectedRowKeys(selectedRowKeys, {
|
||||||
@ -685,7 +675,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ pivot: realIndex });
|
this.setState({ pivot: realIndex });
|
||||||
this.store.setState({
|
this.props.store.setState({
|
||||||
selectionDirty: true,
|
selectionDirty: true,
|
||||||
});
|
});
|
||||||
this.setSelectedRowKeys(selectedRowKeys, {
|
this.setSelectedRowKeys(selectedRowKeys, {
|
||||||
@ -703,7 +693,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
const nativeEvent = e.nativeEvent;
|
const nativeEvent = e.nativeEvent;
|
||||||
const key = this.getRecordKey(record, rowIndex);
|
const key = this.getRecordKey(record, rowIndex);
|
||||||
const selectedRowKeys = [key];
|
const selectedRowKeys = [key];
|
||||||
this.store.setState({
|
this.props.store.setState({
|
||||||
selectionDirty: true,
|
selectionDirty: true,
|
||||||
});
|
});
|
||||||
this.setSelectedRowKeys(selectedRowKeys, {
|
this.setSelectedRowKeys(selectedRowKeys, {
|
||||||
@ -717,8 +707,10 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
|
|
||||||
handleSelectRow = (selectionKey: string, index: number, onSelectFunc: SelectionItemSelectFn) => {
|
handleSelectRow = (selectionKey: string, index: number, onSelectFunc: SelectionItemSelectFn) => {
|
||||||
const data = this.getFlatCurrentPageData();
|
const data = this.getFlatCurrentPageData();
|
||||||
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
|
const defaultSelection = this.props.store.getState().selectionDirty
|
||||||
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
|
? []
|
||||||
|
: this.getDefaultSelection();
|
||||||
|
const selectedRowKeys = this.props.store.getState().selectedRowKeys.concat(defaultSelection);
|
||||||
const changeableRowKeys = data
|
const changeableRowKeys = data
|
||||||
.filter((item, i) => !this.getCheckboxPropsByItem(item, i).disabled)
|
.filter((item, i) => !this.getCheckboxPropsByItem(item, i).disabled)
|
||||||
.map((item, i) => this.getRecordKey(item, i));
|
.map((item, i) => this.getRecordKey(item, i));
|
||||||
@ -763,7 +755,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.store.setState({
|
this.props.store.setState({
|
||||||
selectionDirty: true,
|
selectionDirty: true,
|
||||||
});
|
});
|
||||||
// when select custom selection, callback selections[n].onSelect
|
// when select custom selection, callback selections[n].onSelect
|
||||||
@ -804,7 +796,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
}
|
}
|
||||||
this.setState(newState, () => this.scrollToFirstRow());
|
this.setState(newState, () => this.scrollToFirstRow());
|
||||||
|
|
||||||
this.store.setState({
|
this.props.store.setState({
|
||||||
selectionDirty: false,
|
selectionDirty: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1038,7 +1030,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
<span onClick={stopPropagation}>
|
<span onClick={stopPropagation}>
|
||||||
<SelectionBox
|
<SelectionBox
|
||||||
type={type}
|
type={type}
|
||||||
store={this.store}
|
store={this.props.store}
|
||||||
rowIndex={rowKey}
|
rowIndex={rowKey}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
defaultSelection={this.getDefaultSelection()}
|
defaultSelection={this.getDefaultSelection()}
|
||||||
@ -1087,7 +1079,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
);
|
);
|
||||||
selectionColumn.title = selectionColumn.title || (
|
selectionColumn.title = selectionColumn.title || (
|
||||||
<SelectionCheckboxAll
|
<SelectionCheckboxAll
|
||||||
store={this.store}
|
store={this.props.store}
|
||||||
locale={locale}
|
locale={locale}
|
||||||
data={data}
|
data={data}
|
||||||
getCheckboxPropsByItem={this.getCheckboxPropsByItem}
|
getCheckboxPropsByItem={this.getCheckboxPropsByItem}
|
||||||
@ -1374,3 +1366,40 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
|||||||
return <ConfigConsumer>{this.renderComponent}</ConfigConsumer>;
|
return <ConfigConsumer>{this.renderComponent}</ConfigConsumer>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function withStore(
|
||||||
|
WrappedComponent: typeof Table,
|
||||||
|
): React.ComponentClass<Omit<TableProps<any>, keyof WithStore>> {
|
||||||
|
class Component<T> extends React.Component<TableProps<T>> {
|
||||||
|
store: Store;
|
||||||
|
|
||||||
|
CheckboxPropsCache: CheckboxPropsCache;
|
||||||
|
|
||||||
|
constructor(props: TableProps<T>) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.CheckboxPropsCache = {};
|
||||||
|
|
||||||
|
this.store = createStore({
|
||||||
|
selectedRowKeys: getRowSelection(props).selectedRowKeys || [],
|
||||||
|
selectionDirty: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setCheckboxPropsCache = (cache: CheckboxPropsCache) => (this.CheckboxPropsCache = cache);
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<WrappedComponent<T>
|
||||||
|
{...this.props}
|
||||||
|
store={this.store}
|
||||||
|
checkboxPropsCache={this.CheckboxPropsCache}
|
||||||
|
setCheckboxPropsCache={this.setCheckboxPropsCache}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Component;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStore(Table);
|
||||||
|
@ -61,7 +61,7 @@ describe('Table', () => {
|
|||||||
];
|
];
|
||||||
wrapper.setProps({ columns: newColumns });
|
wrapper.setProps({ columns: newColumns });
|
||||||
|
|
||||||
expect(wrapper.instance().columns).toBe(newColumns);
|
expect(wrapper.dive().instance().columns).toBe(newColumns);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loading with Spin', async () => {
|
it('loading with Spin', async () => {
|
||||||
|
@ -148,7 +148,17 @@ export interface TableEventListeners {
|
|||||||
[name: string]: any; // https://github.com/ant-design/ant-design/issues/17245#issuecomment-504807714
|
[name: string]: any; // https://github.com/ant-design/ant-design/issues/17245#issuecomment-504807714
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableProps<T> {
|
export interface CheckboxPropsCache {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WithStore {
|
||||||
|
store: Store;
|
||||||
|
checkboxPropsCache: CheckboxPropsCache;
|
||||||
|
setCheckboxPropsCache: (cache: CheckboxPropsCache) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableProps<T> extends WithStore {
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
dropdownPrefixCls?: string;
|
dropdownPrefixCls?: string;
|
||||||
rowSelection?: TableRowSelection<T>;
|
rowSelection?: TableRowSelection<T>;
|
||||||
|
@ -63,7 +63,7 @@ export function normalizeColumns(elements: React.ReactChildren) {
|
|||||||
if (element.key) {
|
if (element.key) {
|
||||||
column.key = element.key;
|
column.key = element.key;
|
||||||
}
|
}
|
||||||
if (element.type && (element.type as any).__ANT_TABLE_COLUMN_GROUP) {
|
if (element.props && (element.props as any).children) {
|
||||||
column.children = normalizeColumns(column.children);
|
column.children = normalizeColumns(column.children);
|
||||||
}
|
}
|
||||||
columns.push(column);
|
columns.push(column);
|
||||||
|
Loading…
Reference in New Issue
Block a user