From 2c3a04c5c174b5166f867021a44710a97ff248ea Mon Sep 17 00:00:00 2001
From: dream2023 <1098626505@qq.com>
Date: Wed, 6 Mar 2024 15:17:12 +0800
Subject: [PATCH] fix: schema component options add memo
---
.../src/acl/Configuration/ScopeSelect.tsx | 15 ++++--
.../BlockSchemaComponentProvider.tsx | 50 ++++++++++---------
.../src/block-provider/TableBlockProvider.tsx | 3 +-
.../block-provider/TableSelectorProvider.tsx | 7 +--
.../core/client/src/china-region/index.tsx | 5 +-
.../Configuration/AddCollectionAction.tsx | 15 ++----
.../route-switch/antd/admin-layout/index.tsx | 9 +++-
.../antd/association-field/SubTable.tsx | 42 +++++++++-------
.../antd/grid-card/GridCard.tsx | 12 +++--
.../schema-component/core/SchemaComponent.tsx | 26 ++++++----
.../core/SchemaComponentProvider.tsx | 42 +++++++++-------
.../SystemSettingsShortcut.tsx | 5 +-
.../src/client/ImportPluginProvider.tsx | 29 +++++++----
13 files changed, 152 insertions(+), 108 deletions(-)
diff --git a/packages/core/client/src/acl/Configuration/ScopeSelect.tsx b/packages/core/client/src/acl/Configuration/ScopeSelect.tsx
index 1d4c6e4847..01f95f95bb 100644
--- a/packages/core/client/src/acl/Configuration/ScopeSelect.tsx
+++ b/packages/core/client/src/acl/Configuration/ScopeSelect.tsx
@@ -29,15 +29,20 @@ export const ScopeSelect = (props) => {
}),
[],
);
+
+ const scope = useMemo(() => {
+ return {
+ onChange(value) {
+ props?.onChange?.(value);
+ },
+ };
+ }, [props?.onChange])
+
return (
diff --git a/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx b/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx
index fc08fc1e1e..dcab2dcce4 100644
--- a/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx
+++ b/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useMemo } from 'react';
import { Plugin } from '../application/Plugin';
import { ActionSchemaToolbar } from '../modules/actions/ActionSchemaToolbar';
import { CollapseItemSchemaToolbar } from '../modules/blocks/filter-blocks/collapse/CollapseItemSchemaToolbar';
@@ -18,30 +18,34 @@ import { BlockSchemaToolbar } from '../modules/blocks/BlockSchemaToolbar';
// TODO: delete this, replaced by `BlockSchemaComponentPlugin`
export const BlockSchemaComponentProvider: React.FC = (props) => {
+ const components = useMemo(() => ({
+ TableFieldProvider,
+ TableBlockProvider,
+ TableSelectorProvider,
+ FormBlockProvider,
+ FilterFormBlockProvider,
+ FormFieldProvider,
+ DetailsBlockProvider,
+ RecordLink,
+ }), [])
+
+ const scope = useMemo(() => ({
+ ...bp,
+ useSourceIdFromRecord,
+ useSourceIdFromParentRecord,
+ useParamsFromRecord,
+ useFormBlockProps,
+ useFormFieldProps,
+ useDetailsBlockProps,
+ useTableFieldProps,
+ useTableBlockProps,
+ useTableSelectorProps,
+ }), [])
+
return (
{props.children}
diff --git a/packages/core/client/src/block-provider/TableBlockProvider.tsx b/packages/core/client/src/block-provider/TableBlockProvider.tsx
index 517ef47a21..2c6300da1d 100644
--- a/packages/core/client/src/block-provider/TableBlockProvider.tsx
+++ b/packages/core/client/src/block-provider/TableBlockProvider.tsx
@@ -111,8 +111,9 @@ export const TableBlockProvider = (props) => {
};
}, [parsedFilter, params]);
+ const scope = useMemo(() => ({ treeTable }), [treeTable]);
return (
-
+
diff --git a/packages/core/client/src/block-provider/TableSelectorProvider.tsx b/packages/core/client/src/block-provider/TableSelectorProvider.tsx
index 4d422b8e8d..fbcdd834a3 100644
--- a/packages/core/client/src/block-provider/TableSelectorProvider.tsx
+++ b/packages/core/client/src/block-provider/TableSelectorProvider.tsx
@@ -2,7 +2,7 @@ import { ArrayField } from '@formily/core';
import { Schema, useField, useFieldSchema } from '@formily/react';
import _ from 'lodash';
import uniq from 'lodash/uniq';
-import React, { createContext, useContext, useEffect, useState } from 'react';
+import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { useCollectionManager_deprecated } from '../collection-manager';
import { useCollectionParentRecordData } from '../data-source/collection-record/CollectionRecordProvider';
import { isInFilterFormBlock } from '../filter-provider';
@@ -153,6 +153,8 @@ export const TableSelectorProvider = (props: TableSelectorProviderProps) => {
const collection = getCollection(collectionField?.collectionName);
const primaryKey = collection?.getPrimaryKey();
const appends = useAssociationNames(props.collection);
+ const scope = useMemo(() => ({ treeTable }), [treeTable]);
+
let params = { ...props.params };
if (props.dragSort) {
params['sort'] = ['sort'];
@@ -255,9 +257,8 @@ export const TableSelectorProvider = (props: TableSelectorProviderProps) => {
if (params?.filter) {
params.filter = parsedFilter;
}
-
return (
-
+
diff --git a/packages/core/client/src/china-region/index.tsx b/packages/core/client/src/china-region/index.tsx
index dcbe51d92e..1b3b1a018e 100644
--- a/packages/core/client/src/china-region/index.tsx
+++ b/packages/core/client/src/china-region/index.tsx
@@ -1,7 +1,7 @@
import { ArrayField } from '@formily/core';
import { useField } from '@formily/react';
import { error } from '@nocobase/utils/client';
-import React from 'react';
+import React, { useMemo } from 'react';
import { SchemaComponentOptions } from '..';
import { useAPIClient, useRequest } from '../api-client';
@@ -74,8 +74,9 @@ const useChinaRegionLoadData = () => {
};
export const ChinaRegionProvider = (props) => {
+ const scope = useMemo(() => ({ useChinaRegionDataSource, useChinaRegionLoadData }), []);
return (
-
+
{props.children}
);
diff --git a/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx b/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx
index 82ea4e9939..83dd505b89 100644
--- a/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx
+++ b/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx
@@ -180,6 +180,9 @@ export const AddCollectionAction = (props) => {
};
}, [category, items]);
+ const components = useMemo(() => ({ ...components, ArrayTable, TemplateSummary }), []);
+ const scopes = useMemo(() => ({ getContainer, useCancelAction, useCreateCollection, record, ...scope }), [scope]);
+
return (
@@ -192,16 +195,8 @@ export const AddCollectionAction = (props) => {
diff --git a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx
index f237c81f62..a17a949ff3 100644
--- a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx
+++ b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx
@@ -199,12 +199,19 @@ const MenuEditor = (props) => {
},
);
+ const scope = useMemo(() => ({
+ useMenuProps,
+ onSelect,
+ sideMenuRef,
+ defaultSelectedUid
+ }), [])
+
if (loading) {
return render();
}
return (
-
+
);
};
diff --git a/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx b/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx
index 4e31ebc648..91ad692977 100644
--- a/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx
+++ b/packages/core/client/src/schema-component/antd/association-field/SubTable.tsx
@@ -29,6 +29,22 @@ import { useTableSelectorProps } from './InternalPicker';
import { getLabelFormatValue, useLabelUiSchema } from './util';
import { markRecordAsNew } from '../../../data-source/collection-record/isNewRecord';
+
+const usePickActionProps = () => {
+ const { setVisible } = useActionContext();
+ const { selectedRows, options, collectionField } = useContext(RecordPickerContext);
+ const { field } = useAssociationFieldContext();
+ return {
+ onClick() {
+ const selectData = unionBy(selectedRows, options, collectionField?.targetKey || 'id');
+ const data = field.value || [];
+ field.value = uniqBy(data.concat(selectData), collectionField?.targetKey || 'id');
+ field.onInput(field.value);
+ setVisible(false);
+ },
+ };
+};
+
export const SubTable: any = observer(
(props: any) => {
const { openSize } = props;
@@ -88,25 +104,19 @@ export const SubTable: any = observer(
setSelectedRows,
collectionField,
};
- const usePickActionProps = () => {
- const { setVisible } = useActionContext();
- const { selectedRows, options, collectionField } = useContext(RecordPickerContext);
- return {
- onClick() {
- const selectData = unionBy(selectedRows, options, collectionField?.targetKey || 'id');
- const data = field.value || [];
- field.value = uniqBy(data.concat(selectData), collectionField?.targetKey || 'id');
- field.onInput(field.value);
- setVisible(false);
- },
- };
- };
const getFilter = () => {
const targetKey = collectionField?.targetKey || 'id';
const list = options.map((option) => option[targetKey]).filter(Boolean);
const filter = list.length ? { $and: [{ [`${targetKey}.$ne`]: list }] } : {};
return filter;
};
+
+ const scope = useMemo(() => ({
+ usePickActionProps,
+ useTableSelectorProps,
+ useCreateActionProps,
+ }), []);
+
return (
{
[run, params],
);
+ const scope = useMemo(() => ({
+ useGridCardItemProps,
+ useGridCardActionBarProps,
+ }), [])
+
return (
toSchema(schema), [schema]);
+ const refresh = useCallback(() => {
+ ctx.refresh?.();
+ props.onChange?.(s);
+ }, [s, ctx.refresh, props.onChange]);
+
+ const contextValue = useMemo(() => ({
+ ...ctx,
+ refresh
+ }), [ctx, refresh]);
+
return (
{
- ctx.refresh?.();
- props.onChange?.(s);
- },
- }}
+ value={contextValue}
>
@@ -53,7 +57,7 @@ const MemoizedSchemaComponent = (props: ISchemaFieldProps & SchemaComponentOnCha
return ;
};
-export const SchemaComponent = (
+export const SchemaComponent = memo((
props: (ISchemaFieldProps | IRecursionFieldProps) & { memoized?: boolean } & SchemaComponentOnChange,
) => {
const { memoized, ...others } = props;
@@ -61,4 +65,6 @@ export const SchemaComponent = (
return ;
}
return ;
-};
+});
+
+SchemaComponent.displayName = 'SchemaComponent';
diff --git a/packages/core/client/src/schema-component/core/SchemaComponentProvider.tsx b/packages/core/client/src/schema-component/core/SchemaComponentProvider.tsx
index 39358a4e70..28fa7d1525 100644
--- a/packages/core/client/src/schema-component/core/SchemaComponentProvider.tsx
+++ b/packages/core/client/src/schema-component/core/SchemaComponentProvider.tsx
@@ -1,7 +1,7 @@
import { createForm } from '@formily/core';
import { FormProvider, Schema } from '@formily/react';
import { uid } from '@formily/shared';
-import React, { useMemo, useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaComponentContext } from '../context';
import { ISchemaComponentProvider } from '../types';
@@ -53,27 +53,35 @@ export const SchemaComponentProvider: React.FC = (prop
}, [props.scope, t]);
const [active, setActive] = useState(designable);
- const schemaComponentContextValue = useMemo(
- () => ({
+ const refresh = useCallback(() => {
+ setUid(uid());
+ }, []);
+
+ const reset = useCallback(() => {
+ setFormId(uid());
+ }, []);
+ const setDesignable = useCallback((value) => {
+ if (typeof designable !== 'boolean') {
+ setActive(value);
+ }
+ onDesignableChange?.(value);
+ }, [designable, onDesignableChange]);
+
+ const contextValue = useMemo(() => {
+ return {
scope,
components,
- reset: () => setFormId(uid()),
- refresh: () => {
- setUid(uid());
- },
+ reset,
+ refresh,
designable: typeof designable === 'boolean' ? designable : active,
- setDesignable: (value) => {
- if (typeof designable !== 'boolean') {
- setActive(value);
- }
- onDesignableChange?.(value);
- },
- }),
- [uidValue, scope, components, designable, active],
- );
+ setDesignable,
+ };
+
+ // uidValue 虽然没用到,但是这里必须加上,为了让整个页面能够渲染
+ }, [uidValue, scope, components, reset, refresh, designable, active, setDesignable])
return (
-
+
{children}
diff --git a/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx b/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx
index 6362f6f0ed..470cb8a148 100644
--- a/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx
+++ b/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx
@@ -2,7 +2,7 @@ import { ISchema, useForm } from '@formily/react';
import { uid } from '@formily/shared';
import { Card, message } from 'antd';
import cloneDeep from 'lodash/cloneDeep';
-import React from 'react';
+import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useSystemSettings } from '.';
import { i18n, useAPIClient, useRequest } from '..';
@@ -164,10 +164,11 @@ const schema: ISchema = {
};
export const SystemSettingsPane = () => {
+ const scope = useMemo(() => ({ useSaveSystemSettingsValues, useSystemSettingsValues, useCloseAction }), []);
return (
diff --git a/packages/plugins/@nocobase/plugin-import/src/client/ImportPluginProvider.tsx b/packages/plugins/@nocobase/plugin-import/src/client/ImportPluginProvider.tsx
index 17e1133183..9f0146bd53 100644
--- a/packages/plugins/@nocobase/plugin-import/src/client/ImportPluginProvider.tsx
+++ b/packages/plugins/@nocobase/plugin-import/src/client/ImportPluginProvider.tsx
@@ -1,5 +1,5 @@
import { SchemaComponentOptions } from '@nocobase/client';
-import React, { useState } from 'react';
+import React, { memo, useMemo, useState } from 'react';
import { createPortal } from 'react-dom';
import { ImportActionInitializer, ImportDesigner } from '.';
import { ImportContext } from './context';
@@ -9,23 +9,30 @@ import { useShared } from './useShared';
export const ImportPluginProvider = (props: any) => {
const { uploadValidator, beforeUploadHandler, validateUpload } = useShared();
+ const scope = useMemo(() => ({
+ uploadValidator,
+ validateUpload,
+ beforeUploadHandler,
+ useDownloadXlsxTemplateAction,
+ useImportStartAction,
+ }), [uploadValidator, beforeUploadHandler, validateUpload])
+
+ const components = useMemo(() => ({
+ ImportActionInitializer,
+ ImportDesigner,
+ }), []);
+
return (
{props.children}
);
};
-export const ImportContextProvider = (props: any) => {
+export const ImportContextProvider = memo((props: any) => {
const [importModalVisible, setImportModalVisible] = useState(false);
const [importStatus, setImportStatus] = useState(ImportStatus.IMPORTING);
const [importResult, setImportResult] = useState<{
@@ -47,4 +54,4 @@ export const ImportContextProvider = (props: any) => {
{props.children}
);
-};
+});