diff --git a/packages/client/intro.md b/packages/client/intro.md index 9797cbcda..2cf96c52f 100644 --- a/packages/client/intro.md +++ b/packages/client/intro.md @@ -473,7 +473,7 @@ export default function App() { * defaultShowCode: true * title: RouteSwitch + SchemaComponent */ -import React, { useMemo } from 'react'; +import React, { useMemo, useEffect } from 'react'; import { Link, MemoryRouter as Router } from 'react-router-dom'; import { RouteRedirectProps, @@ -483,6 +483,7 @@ import { SchemaComponentProvider, SchemaComponent, useDesignable, + useSchemaComponentContext, } from '@nocobase/client'; import { Spin, Button } from 'antd'; import { observer, Schema } from '@formily/react'; @@ -503,6 +504,10 @@ const Hello = observer(({ name }) => { const RouteSchemaComponent = (props) => { const route = useRoute(); + const { reset } = useSchemaComponentContext(); + useEffect(() => { + reset(); + }, route.schema); return } diff --git a/packages/client/package.json b/packages/client/package.json index 7e78db20b..cfe42da8d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -27,7 +27,8 @@ "axios": "^0.24.0", "i18next": "^21.6.0", "react-helmet": "^6.1.0", - "react-i18next": "^11.15.1" + "react-i18next": "^11.15.1", + "use-deep-compare-effect": "^1.8.1" }, "peerDependencies": { "@types/react": ">=16.8.0 || >=17.0.0", diff --git a/packages/client/src/application/demos/demo2/index.tsx b/packages/client/src/application/demos/demo2/index.tsx index 5bfe6ac67..674512eda 100644 --- a/packages/client/src/application/demos/demo2/index.tsx +++ b/packages/client/src/application/demos/demo2/index.tsx @@ -1,28 +1,28 @@ -import React from 'react'; -import { HashRouter, MemoryRouter } from 'react-router-dom'; import { - i18n, - compose, - useRequest, - AuthLayout, + ACLShortcut, + Action, AdminLayout, + AntdConfigProvider, APIClientProvider, + AuthLayout, + CollectionManagerShortcut, + compose, + DesignableSwitch, + DocumentTitleProvider, + i18n, + Menu, + Page, + PluginManagerProvider, RouteSwitch, RouteSwitchProvider, - AntdConfigProvider, SchemaComponentProvider, - Menu, - Action, - PluginManagerProvider, - DesignableSwitch, - CollectionManagerShortcut, - ACLShortcut, SystemSettingsShortcut, - DocumentTitleProvider, - Page, + useRequest } from '@nocobase/client'; -import { I18nextProvider } from 'react-i18next'; import { Spin } from 'antd'; +import React from 'react'; +import { I18nextProvider } from 'react-i18next'; +import { MemoryRouter } from 'react-router-dom'; import apiClient from './apiClient'; const providers = [ diff --git a/packages/client/src/plugin-manager/PluginManager.tsx b/packages/client/src/plugin-manager/PluginManager.tsx index fb46b0dbc..cf7e12744 100644 --- a/packages/client/src/plugin-manager/PluginManager.tsx +++ b/packages/client/src/plugin-manager/PluginManager.tsx @@ -43,11 +43,11 @@ PluginManager.Toolbar = (props: ToolbarProps) => { {items .filter((item) => item.pin) - .map((item) => { + .map((item, index) => { const Action = get(components, item.component); return ( Action && ( - + ) @@ -56,18 +56,18 @@ PluginManager.Toolbar = (props: ToolbarProps) => { }> {items .filter((item) => !item.pin) - .map((item) => { + .map((item, index) => { const Action = get(components, item.component); return ( Action && ( - + ) ); })} - - }> + + }> 管理插件 diff --git a/packages/client/src/schema-component/antd/cascader/Cascader.tsx b/packages/client/src/schema-component/antd/cascader/Cascader.tsx index c7f8898c9..786c236c6 100644 --- a/packages/client/src/schema-component/antd/cascader/Cascader.tsx +++ b/packages/client/src/schema-component/antd/cascader/Cascader.tsx @@ -21,6 +21,7 @@ export const Cascader = connect( useLoadData = useDefLoadData, changeOnSelectLast, changeOnSelect, + maxLevel, ...others } = props; const loadData = useLoadData(props); diff --git a/packages/client/src/schema-component/antd/cascader/demos/demo2.tsx b/packages/client/src/schema-component/antd/cascader/demos/demo2.tsx index ff8abfccc..e7fbbfb61 100644 --- a/packages/client/src/schema-component/antd/cascader/demos/demo2.tsx +++ b/packages/client/src/schema-component/antd/cascader/demos/demo2.tsx @@ -34,6 +34,7 @@ mock.onGet('/china_regions').reply(200, { const useAsyncDataSource = (api: APIClient) => (field) => { field.loading = true; + console.log('useAsyncDataSource'); api.request({ url: 'china_regions' }).then( action.bound((res) => { field.dataSource = res?.data?.data || []; diff --git a/packages/client/src/schema-component/antd/menu/Menu.tsx b/packages/client/src/schema-component/antd/menu/Menu.tsx index b9547a653..1dab6237d 100644 --- a/packages/client/src/schema-component/antd/menu/Menu.tsx +++ b/packages/client/src/schema-component/antd/menu/Menu.tsx @@ -1,8 +1,8 @@ +import { DesktopOutlined } from '@ant-design/icons'; +import { observer, RecursionField, Schema, useFieldSchema } from '@formily/react'; +import { Menu as AntdMenu } from 'antd'; import React, { createContext, useContext, useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; -import { Menu as AntdMenu } from 'antd'; -import { Schema, observer, useFieldSchema, RecursionField } from '@formily/react'; -import { DesktopOutlined } from '@ant-design/icons'; import { findKeysByUid, findMenuItem } from './util'; type ComposedMenu = React.FC & { @@ -22,6 +22,7 @@ export const Menu: ComposedMenu = observer((props) => { defaultOpenKeys: dOpenKeys, ...others } = props; + console.log('defaultSelectedUid', defaultSelectedUid) const schema = useFieldSchema(); const [defaultSelectedKeys, setDefaultSelectedKeys] = useState(() => { if (dSelectedKeys) { diff --git a/packages/client/src/schema-component/components/RemoteSchemaComponent.tsx b/packages/client/src/schema-component/components/RemoteSchemaComponent.tsx index bff72ab84..79718ec25 100644 --- a/packages/client/src/schema-component/components/RemoteSchemaComponent.tsx +++ b/packages/client/src/schema-component/components/RemoteSchemaComponent.tsx @@ -1,8 +1,9 @@ -import React from 'react'; -import { Spin } from 'antd'; -import { useRequest } from '../../api-client'; -import { SchemaComponent } from './SchemaComponent'; import { Schema } from '@formily/react'; +import { Spin } from 'antd'; +import React from 'react'; +import { useRequest } from '../../api-client'; +import { useSchemaComponentContext } from '../hooks'; +import { SchemaComponent } from './SchemaComponent'; export interface RemoteSchemaComponentProps { scope?: any; @@ -15,20 +16,22 @@ export interface RemoteSchemaComponentProps { const defaultTransform = (s: Schema) => s; -export const RemoteSchemaComponent: React.FC = (props) => { +const RequestSchemaComponent: React.FC = (props) => { const { hidden, scope, uid, onSuccess, schemaTransform = defaultTransform } = props; - if (!uid) { - return null; - } + const { reset } = useSchemaComponentContext(); const { data, loading } = useRequest( { url: `/ui_schemas:getJsonSchema/${uid}`, }, { refreshDeps: [uid], - onSuccess, + onSuccess(data) { + onSuccess && onSuccess(data); + reset && reset(); + }, }, ); + if (loading) { return ; } @@ -37,3 +40,7 @@ export const RemoteSchemaComponent: React.FC = (prop } return ; }; + +export const RemoteSchemaComponent: React.FC = (props) => { + return props.uid ? : null; +}; diff --git a/packages/client/src/schema-component/components/SchemaComponent.tsx b/packages/client/src/schema-component/components/SchemaComponent.tsx index 8ab13b8c5..ebc7afaab 100644 --- a/packages/client/src/schema-component/components/SchemaComponent.tsx +++ b/packages/client/src/schema-component/components/SchemaComponent.tsx @@ -1,5 +1,5 @@ import { ISchemaFieldProps, Schema } from '@formily/react'; -import React, { useContext, useEffect, useMemo, useRef } from 'react'; +import React, { useContext, useMemo } from 'react'; import { SchemaComponentContext } from '../context'; function toSchema(schema?: any) { @@ -18,16 +18,8 @@ function toSchema(schema?: any) { } export function SchemaComponent(props: ISchemaFieldProps) { - const { schema: defaultSchema, ...others } = props; - const { reset, SchemaField } = useContext(SchemaComponentContext); - const schema = useMemo(() => toSchema(defaultSchema), []); - const isInitialMount = useRef(true); - useEffect(() => { - if (isInitialMount.current) { - isInitialMount.current = false; - } else { - reset(); - } - }, [JSON.stringify(defaultSchema)]); - return ; + const { schema, ...others } = props; + const { SchemaField } = useContext(SchemaComponentContext); + const s = useMemo(() => toSchema(schema), []); + return ; } diff --git a/packages/client/src/schema-component/components/SchemaComponentProvider.tsx b/packages/client/src/schema-component/components/SchemaComponentProvider.tsx index 19de5c216..1eff9ce4b 100644 --- a/packages/client/src/schema-component/components/SchemaComponentProvider.tsx +++ b/packages/client/src/schema-component/components/SchemaComponentProvider.tsx @@ -29,7 +29,6 @@ export const SchemaComponentProvider: React.FC = (prop SchemaField, components, scope, - refreshFormId: () => setFormId(uid()), reset: () => setFormId(uid()), refresh: () => setUid(uid()), designable: active === 'true', diff --git a/packages/client/src/schema-component/hooks/index.ts b/packages/client/src/schema-component/hooks/index.ts index d377e5aa7..44019bb65 100644 --- a/packages/client/src/schema-component/hooks/index.ts +++ b/packages/client/src/schema-component/hooks/index.ts @@ -2,4 +2,5 @@ export * from './useAttach'; export * from './useCompile'; export * from './useDesignable'; export * from './useFieldProps'; +export * from './useSchemaComponentContext'; diff --git a/packages/client/src/schema-component/hooks/useCompile.ts b/packages/client/src/schema-component/hooks/useCompile.ts index 4fbd7150b..b229fb616 100644 --- a/packages/client/src/schema-component/hooks/useCompile.ts +++ b/packages/client/src/schema-component/hooks/useCompile.ts @@ -1,9 +1,11 @@ +import { useContext } from 'react'; import { compile } from '@formily/json-schema/lib/compiler'; -import { useTranslation } from 'react-i18next'; +import { SchemaExpressionScopeContext, SchemaOptionsContext } from '@formily/react'; export const useCompile = () => { - const { t } = useTranslation(); + const options = useContext(SchemaOptionsContext); + const scope = useContext(SchemaExpressionScopeContext); return (source: any) => { - return compile(source, { t }); + return compile(source, { ...options.scope, ...scope }); }; }; diff --git a/packages/client/src/schema-component/hooks/useSchemaComponentContext.ts b/packages/client/src/schema-component/hooks/useSchemaComponentContext.ts new file mode 100644 index 000000000..9bdab5dbd --- /dev/null +++ b/packages/client/src/schema-component/hooks/useSchemaComponentContext.ts @@ -0,0 +1,6 @@ +import { useContext } from 'react'; +import { SchemaComponentContext } from '../context'; + +export function useSchemaComponentContext() { + return useContext(SchemaComponentContext); +} diff --git a/packages/client/src/schema-component/index.md b/packages/client/src/schema-component/index.md index 4eb18d482..f7e37c95f 100644 --- a/packages/client/src/schema-component/index.md +++ b/packages/client/src/schema-component/index.md @@ -17,6 +17,14 @@ group: ## Hooks +### useSchemaComponentContext() + +获取 SchemaComponent 的上下文 + +```ts +const { refresh, reset } = useSchemaComponentContext(); +``` + ### useDesignable() 获取当前 schema 节点设计器的 API diff --git a/packages/client/src/schema-component/types.ts b/packages/client/src/schema-component/types.ts index d5aad72ce..a07d6ab73 100644 --- a/packages/client/src/schema-component/types.ts +++ b/packages/client/src/schema-component/types.ts @@ -19,7 +19,6 @@ export interface ISchemaComponentContext { scope?: any; components?: SchemaReactComponents; refresh?: () => void; - refreshFormId?: () => void; reset?: () => void; designable?: boolean; setDesignable?: (value: boolean) => void; diff --git a/yarn.lock b/yarn.lock index cddeff563..b09778962 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5452,6 +5452,11 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== +dequal@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d" + integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug== + des.js@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -14631,6 +14636,14 @@ urllib@^2.33.1: statuses "^1.3.1" utility "^1.16.1" +use-deep-compare-effect@^1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/use-deep-compare-effect/-/use-deep-compare-effect-1.8.1.tgz#ef0ce3b3271edb801da1ec23bf0754ef4189d0c6" + integrity sha512-kbeNVZ9Zkc0RFGpfMN3MNfaKNvcLNyxOAAd9O4CBZ+kCBXXscn9s/4I+8ytUER4RDpEYs5+O6Rs4PqiZ+rHr5Q== + dependencies: + "@babel/runtime" "^7.12.5" + dequal "^2.0.2" + use-subscription@1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"