perf(FilterProvider): use startTransition

This commit is contained in:
Zeke Zhang 2024-10-27 18:49:43 +08:00
parent 898a9910bb
commit 5ac6e107ca

View File

@ -8,8 +8,7 @@
*/
import { useField, useFieldSchema } from '@formily/react';
import { uniqBy } from 'lodash';
import React, { createContext, useCallback, useEffect, useRef } from 'react';
import _, { uniqBy } from 'lodash';
import { CollectionFieldOptions_deprecated } from '../collection-manager';
import { Collection } from '../data-source/collection/Collection';
import { useCollection } from '../data-source/collection/CollectionProvider';
@ -18,6 +17,9 @@ import { useDataLoadingMode } from '../modules/blocks/data-blocks/details-multi/
import { removeNullCondition } from '../schema-component';
import { mergeFilter, useAssociatedFields } from './utils';
// @ts-ignore
import React, { createContext, startTransition, useCallback, useEffect, useMemo, useRef } from 'react';
enum FILTER_OPERATOR {
AND = '$and',
OR = '$or',
@ -83,8 +85,19 @@ FilterContext.displayName = 'FilterContext';
* @returns
*/
export const FilterBlockProvider: React.FC = ({ children }) => {
const [dataBlocks, setDataBlocks] = React.useState<DataBlock[]>([]);
return <FilterContext.Provider value={{ dataBlocks, setDataBlocks }}>{children}</FilterContext.Provider>;
const [dataBlocks, _setDataBlocks] = React.useState<DataBlock[]>([]);
const setDataBlocks = useCallback((value) => {
startTransition(() => {
_setDataBlocks(value);
});
}, []);
const value = useMemo(() => {
return { dataBlocks, setDataBlocks };
}, [dataBlocks, setDataBlocks]);
return <FilterContext.Provider value={value}>{children}</FilterContext.Provider>;
};
/**
@ -172,33 +185,41 @@ export const DataBlockCollector = ({
*/
export const useFilterBlock = () => {
const ctx = React.useContext(FilterContext);
// 有可能存在页面没有提供 FilterBlockProvider 的情况,比如内部使用的数据表管理页面
const getDataBlocks = useCallback<() => DataBlock[]>(() => ctx?.dataBlocks || [], [ctx?.dataBlocks]);
const recordDataBlocks = useCallback(
(block: DataBlock) => {
const existingBlock = ctx?.dataBlocks.find((item) => item.uid === block.uid);
if (existingBlock) {
// 这里的值有可能会变化,所以需要更新
Object.assign(existingBlock, block);
return;
}
// 由于 setDataBlocks 是异步操作,所以上面的 existingBlock 在判断时有可能用的是旧的 dataBlocks,所以下面还需要根据 uid 进行去重操作
ctx?.setDataBlocks((prev) => uniqBy([...prev, block], 'uid'));
},
[ctx],
);
const removeDataBlock = useCallback(
(uid: string) => {
if (ctx?.dataBlocks.every((item) => item.uid !== uid)) return;
ctx?.setDataBlocks((prev) => prev.filter((item) => item.uid !== uid));
},
[ctx],
);
if (!ctx) {
return {
inProvider: false,
recordDataBlocks: () => {},
recordDataBlocks: _.noop,
getDataBlocks,
removeDataBlock: () => {},
removeDataBlock: _.noop,
};
}
const { dataBlocks, setDataBlocks } = ctx;
const recordDataBlocks = (block: DataBlock) => {
const existingBlock = dataBlocks.find((item) => item.uid === block.uid);
if (existingBlock) {
// 这里的值有可能会变化,所以需要更新
Object.assign(existingBlock, block);
return;
}
// 由于 setDataBlocks 是异步操作,所以上面的 existingBlock 在判断时有可能用的是旧的 dataBlocks,所以下面还需要根据 uid 进行去重操作
setDataBlocks((prev) => uniqBy([...prev, block], 'uid'));
};
const removeDataBlock = (uid: string) => {
if (dataBlocks.every((item) => item.uid !== uid)) return;
setDataBlocks((prev) => prev.filter((item) => item.uid !== uid));
};
return {
recordDataBlocks,