mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 19:19:57 +08:00
fix: 4.0 table filters value may be previous (#19873)
* fix: 4.0 table filters value may be previous * create a sync variable to resolve async 'setFilteredKeys' * useSyncState to fix 'setFilteredKeys' async * new line * new line * add , * removed 'setFilteredKeys' and re-render useSyncState * menu must be a array
This commit is contained in:
parent
5fc62314af
commit
221d404986
@ -123,6 +123,15 @@ describe('Table.filter', () => {
|
||||
<span onClick={() => clearFilters()} id="reset">
|
||||
Reset
|
||||
</span>
|
||||
<span
|
||||
onClick={() => {
|
||||
setSelectedKeys([43]);
|
||||
confirm();
|
||||
}}
|
||||
id="simulateOnSelect"
|
||||
>
|
||||
SimulateOnSelect
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -170,6 +179,11 @@ describe('Table.filter', () => {
|
||||
.first()
|
||||
.props().visible,
|
||||
).toBeFalsy();
|
||||
|
||||
// Simulate onSelect, setSelectedKeys & confirm
|
||||
wrapper.find('span.ant-dropdown-trigger').simulate('click', nativeEvent);
|
||||
wrapper.find('#simulateOnSelect').simulate('click');
|
||||
expect(getFilterMenu().props().filterState.filteredKeys).toEqual([43]);
|
||||
});
|
||||
|
||||
it('can be controlled by filterDropdownVisible', () => {
|
||||
|
@ -23,6 +23,12 @@ exports[`Table.filter override custom filter correctly 1`] = `
|
||||
>
|
||||
Reset
|
||||
</span>
|
||||
<span
|
||||
id="simulateOnSelect"
|
||||
onClick={[Function]}
|
||||
>
|
||||
SimulateOnSelect
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -9,6 +9,7 @@ import Dropdown from '../../../dropdown';
|
||||
import { ColumnType, ColumnFilterItem, Key, TableLocale, GetPopupContainer } from '../../interface';
|
||||
import FilterDropdownMenuWrapper from './FilterWrapper';
|
||||
import { FilterState } from '.';
|
||||
import useSyncState from '../useSyncState';
|
||||
|
||||
const { SubMenu, Item: MenuItem } = Menu;
|
||||
|
||||
@ -91,21 +92,21 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
const [propFilteredKeys, setPropFilteredKeys] = React.useState(
|
||||
filterState && filterState.filteredKeys,
|
||||
);
|
||||
const [filteredKeys, setFilteredKeys] = React.useState(propFilteredKeys || []);
|
||||
const [getFilteredKeysSync, setFilteredKeysSync] = useSyncState(propFilteredKeys || []);
|
||||
|
||||
const onSelectKeys = ({ selectedKeys }: { selectedKeys: Key[] }) => {
|
||||
setFilteredKeysSync(selectedKeys);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
// Sync internal filtered keys when props key changed
|
||||
const newFilteredKeys = filterState && filterState.filteredKeys;
|
||||
if (!shallowEqual(propFilteredKeys, newFilteredKeys)) {
|
||||
setPropFilteredKeys(newFilteredKeys);
|
||||
setFilteredKeys(newFilteredKeys || []);
|
||||
onSelectKeys({ selectedKeys: newFilteredKeys || [] });
|
||||
}
|
||||
}, [filterState]);
|
||||
|
||||
const onSelectKeys = ({ selectedKeys }: { selectedKeys: Key[] }) => {
|
||||
setFilteredKeys(selectedKeys);
|
||||
};
|
||||
|
||||
// ====================== Open Keys ======================
|
||||
const [openKeys, setOpenKeys] = React.useState<string[]>([]);
|
||||
const openRef = React.useRef<number>();
|
||||
@ -140,7 +141,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
};
|
||||
|
||||
const onConfirm = () => {
|
||||
internalTriggerFilter(filteredKeys);
|
||||
internalTriggerFilter(getFilteredKeysSync());
|
||||
};
|
||||
|
||||
const onReset = () => {
|
||||
@ -167,7 +168,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
dropdownContent = column.filterDropdown({
|
||||
prefixCls: `${dropdownPrefixCls}-custom`,
|
||||
setSelectedKeys: (selectedKeys: Key[]) => onSelectKeys({ selectedKeys }),
|
||||
selectedKeys: filteredKeys,
|
||||
selectedKeys: getFilteredKeysSync(),
|
||||
confirm: onConfirm,
|
||||
clearFilters: onReset,
|
||||
filters: column.filters,
|
||||
@ -185,12 +186,12 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
||||
onClick={onMenuClick}
|
||||
onSelect={onSelectKeys}
|
||||
onDeselect={onSelectKeys}
|
||||
selectedKeys={(filteredKeys || []) as any}
|
||||
selectedKeys={(getFilteredKeysSync() || []) as any}
|
||||
getPopupContainer={getPopupContainer}
|
||||
openKeys={openKeys}
|
||||
onOpenChange={onOpenChange}
|
||||
>
|
||||
{renderFilterItems(column.filters!, prefixCls, filteredKeys, filterMultiple)}
|
||||
{renderFilterItems(column.filters!, prefixCls, getFilteredKeysSync(), filterMultiple)}
|
||||
</Menu>
|
||||
<div className={`${prefixCls}-dropdown-btns`}>
|
||||
<a className={`${prefixCls}-dropdown-link confirm`} onClick={onConfirm}>
|
||||
|
17
components/table/hooks/useSyncState.ts
Normal file
17
components/table/hooks/useSyncState.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type UseSyncStateProps<T> = [() => T, (newValue: T) => void];
|
||||
|
||||
export default function useSyncState<T>(filteredKeys: T): UseSyncStateProps<T> {
|
||||
const filteredKeysRef = React.useRef<T>(filteredKeys);
|
||||
const [, forceUpdate] = React.useState<T>();
|
||||
|
||||
return [
|
||||
() => filteredKeysRef.current,
|
||||
(newValue: T) => {
|
||||
filteredKeysRef.current = newValue;
|
||||
// re-render
|
||||
forceUpdate(filteredKeys);
|
||||
},
|
||||
];
|
||||
}
|
Loading…
Reference in New Issue
Block a user