mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 23:36:15 +00:00
perf(TableBlockProvider): prevent unnecessary re-renders by splitting context
This commit is contained in:
parent
063c2f7160
commit
583ab0b54b
@ -22,6 +22,12 @@ import { useBlockHeightProps } from './hooks';
|
||||
export const TableBlockContext = createContext<any>({});
|
||||
TableBlockContext.displayName = 'TableBlockContext';
|
||||
|
||||
const TableBlockContextBasicValue = createContext<{
|
||||
field: any;
|
||||
rowKey: string;
|
||||
}>(null);
|
||||
TableBlockContextBasicValue.displayName = 'TableBlockContextBasicValue';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ -61,7 +67,7 @@ const InternalTableBlockProvider = (props: Props) => {
|
||||
childrenColumnName,
|
||||
expandFlag: propsExpandFlag = false,
|
||||
fieldNames,
|
||||
...others
|
||||
collection,
|
||||
} = props;
|
||||
const field: any = useField();
|
||||
const { resource, service } = useBlockRequestContext();
|
||||
@ -89,25 +95,52 @@ const InternalTableBlockProvider = (props: Props) => {
|
||||
[expandFlag],
|
||||
);
|
||||
|
||||
// Split from value to prevent unnecessary re-renders
|
||||
const basicValue = useMemo(
|
||||
() => ({
|
||||
field,
|
||||
rowKey,
|
||||
}),
|
||||
[field, rowKey],
|
||||
);
|
||||
|
||||
// Keep the original for compatibility
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
collection,
|
||||
field,
|
||||
service,
|
||||
resource,
|
||||
params,
|
||||
showIndex,
|
||||
dragSort,
|
||||
rowKey,
|
||||
expandFlag,
|
||||
childrenColumnName,
|
||||
allIncludesChildren,
|
||||
setExpandFlag: setExpandFlagValue,
|
||||
heightProps,
|
||||
}),
|
||||
[
|
||||
allIncludesChildren,
|
||||
childrenColumnName,
|
||||
collection,
|
||||
dragSort,
|
||||
expandFlag,
|
||||
field,
|
||||
heightProps,
|
||||
params,
|
||||
resource,
|
||||
rowKey,
|
||||
service,
|
||||
setExpandFlagValue,
|
||||
showIndex,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<TableBlockContext.Provider
|
||||
value={{
|
||||
...others,
|
||||
field,
|
||||
service,
|
||||
resource,
|
||||
params,
|
||||
showIndex,
|
||||
dragSort,
|
||||
rowKey,
|
||||
expandFlag,
|
||||
childrenColumnName,
|
||||
allIncludesChildren,
|
||||
setExpandFlag: setExpandFlagValue,
|
||||
heightProps,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
<TableBlockContext.Provider value={value}>
|
||||
<TableBlockContextBasicValue.Provider value={basicValue}>{props.children}</TableBlockContextBasicValue.Provider>
|
||||
</TableBlockContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -188,3 +221,10 @@ export const TableBlockProvider = withDynamicSchemaProps((props) => {
|
||||
export const useTableBlockContext = () => {
|
||||
return useContext(TableBlockContext);
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const useTableBlockContextBasicValue = () => {
|
||||
return useContext(TableBlockContextBasicValue);
|
||||
};
|
||||
|
@ -203,3 +203,10 @@ export const useDataBlockRequestGetter = () => {
|
||||
[contextRef],
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* When only data is needed, it's recommended to use this hook to avoid unnecessary re-renders
|
||||
*/
|
||||
export const useDataBlockRequestData = () => {
|
||||
return useContext(BlockRequestDataContext);
|
||||
};
|
||||
|
@ -11,7 +11,7 @@ import { ISchema, useFieldSchema } from '@formily/react';
|
||||
import _ from 'lodash';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useLocationNoUpdate, useNavigateNoUpdate } from '../../../application';
|
||||
import { useTableBlockContext } from '../../../block-provider/TableBlockProvider';
|
||||
import { useTableBlockContextBasicValue } from '../../../block-provider/TableBlockProvider';
|
||||
import {
|
||||
CollectionRecord,
|
||||
useAssociationName,
|
||||
@ -19,6 +19,7 @@ import {
|
||||
useCollectionManager,
|
||||
useCollectionParentRecord,
|
||||
useCollectionRecord,
|
||||
useDataBlockRequestData,
|
||||
useDataBlockRequestGetter,
|
||||
useDataSourceKey,
|
||||
} from '../../../data-source';
|
||||
@ -50,7 +51,7 @@ export interface PopupContextStorage extends PopupContext {
|
||||
service?: any;
|
||||
sourceId?: string;
|
||||
/** Specifically prepared for the 'Table selected records' variable */
|
||||
tableBlockContext?: { field: any; service: any; rowKey: any; collection: string };
|
||||
tableBlockContext?: { field: any; blockData: any; rowKey: any; collection: string };
|
||||
}
|
||||
|
||||
const popupsContextStorage: Record<string, PopupContextStorage> = {};
|
||||
@ -157,7 +158,8 @@ export const usePopupUtils = (
|
||||
(_parentRecordData || parentRecord?.data)?.[cm.getSourceKeyByAssociation(association)],
|
||||
[parentRecord, association],
|
||||
);
|
||||
const tableBlockContext = useTableBlockContext();
|
||||
const blockData = useDataBlockRequestData();
|
||||
const tableBlockContextBasicValue = useTableBlockContextBasicValue() || ({} as any);
|
||||
|
||||
const setVisibleFromAction = options.setVisible || _setVisibleFromAction;
|
||||
|
||||
@ -249,7 +251,7 @@ export const usePopupUtils = (
|
||||
collection: collection?.name,
|
||||
association,
|
||||
sourceId,
|
||||
tableBlockContext,
|
||||
tableBlockContext: { ...tableBlockContextBasicValue, collection: collection?.name, blockData },
|
||||
});
|
||||
|
||||
updatePopupContext(getNewPopupContext(), customActionSchema);
|
||||
@ -271,7 +273,8 @@ export const usePopupUtils = (
|
||||
isPopupVisibleControlledByURL,
|
||||
getSourceId,
|
||||
getNewPopupContext,
|
||||
tableBlockContext,
|
||||
blockData,
|
||||
tableBlockContextBasicValue,
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -8,7 +8,9 @@
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useTableBlockContext } from '../../block-provider/TableBlockProvider';
|
||||
import { useTableBlockContextBasicValue } from '../../block-provider/TableBlockProvider';
|
||||
import { useDataBlockRequestData } from '../../data-source';
|
||||
import { useCollection } from '../../data-source/collection/CollectionProvider';
|
||||
import { useCurrentPopupContext } from '../../schema-component/antd/page/PagePopups';
|
||||
import { getStoredPopupContext } from '../../schema-component/antd/page/pagePopupUtils';
|
||||
import { usePopupSettings } from '../../schema-component/antd/page/PopupSettingsProvider';
|
||||
@ -19,19 +21,21 @@ const useContextVariable = (): VariableOption => {
|
||||
|
||||
const { isPopupVisibleControlledByURL } = usePopupSettings();
|
||||
const { params } = useCurrentPopupContext();
|
||||
const _tableBlockContext = useTableBlockContext();
|
||||
const collection = useCollection();
|
||||
const _blockData = useDataBlockRequestData();
|
||||
const tableBlockContextBasicValue = useTableBlockContextBasicValue() || {};
|
||||
|
||||
if (isPopupVisibleControlledByURL()) {
|
||||
tableBlockContext = getStoredPopupContext(params?.popupuid)?.tableBlockContext;
|
||||
} else {
|
||||
tableBlockContext = _tableBlockContext;
|
||||
tableBlockContext = { ...tableBlockContextBasicValue, collection, blockData: _blockData };
|
||||
}
|
||||
|
||||
const { field, service, rowKey, collection: collectionName } = tableBlockContext || {};
|
||||
const { field, blockData, rowKey, collection: collectionName } = tableBlockContext || {};
|
||||
|
||||
const contextData = useMemo(
|
||||
() => service?.data?.data?.filter((v) => (field?.data?.selectedRowKeys || [])?.includes(v[rowKey])),
|
||||
[field?.data?.selectedRowKeys, rowKey, service?.data?.data],
|
||||
() => blockData?.data?.filter((v) => (field?.data?.selectedRowKeys || [])?.includes(v[rowKey])),
|
||||
[field?.data?.selectedRowKeys, rowKey, blockData],
|
||||
);
|
||||
|
||||
return useMemo(() => {
|
||||
|
Loading…
Reference in New Issue
Block a user