From 5ac6e107ca2591c7a0f2c1c7887d5e3aa32c9848 Mon Sep 17 00:00:00 2001 From: Zeke Zhang <958414905@qq.com> Date: Sun, 27 Oct 2024 18:49:43 +0800 Subject: [PATCH] perf(FilterProvider): use startTransition --- .../src/filter-provider/FilterProvider.tsx | 65 ++++++++++++------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/packages/core/client/src/filter-provider/FilterProvider.tsx b/packages/core/client/src/filter-provider/FilterProvider.tsx index 585d782ace..4b0fc66834 100644 --- a/packages/core/client/src/filter-provider/FilterProvider.tsx +++ b/packages/core/client/src/filter-provider/FilterProvider.tsx @@ -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([]); - return {children}; + const [dataBlocks, _setDataBlocks] = React.useState([]); + + const setDataBlocks = useCallback((value) => { + startTransition(() => { + _setDataBlocks(value); + }); + }, []); + + const value = useMemo(() => { + return { dataBlocks, setDataBlocks }; + }, [dataBlocks, setDataBlocks]); + + return {children}; }; /** @@ -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,