diff --git a/packages/framework/esm-framework/docs/API.md b/packages/framework/esm-framework/docs/API.md index 9b5830e67..2ac065b0d 100644 --- a/packages/framework/esm-framework/docs/API.md +++ b/packages/framework/esm-framework/docs/API.md @@ -1715,7 +1715,7 @@ ___ ### useConfig -▸ **useConfig**<`T`\>(): `T` +▸ **useConfig**<`T`\>(`options?`): `T` Use this React Hook to obtain your module's configuration. @@ -1723,7 +1723,13 @@ Use this React Hook to obtain your module's configuration. | Name | Type | | :------ | :------ | -| `T` | `Omit`<[`ConfigObject`](interfaces/ConfigObject.md), ``"Display conditions"`` \| ``"Translation overrides"``\> | +| `T` | `Record`<`string`, `any`\> | + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `options?` | `UseConfigOptions` | Additional options that can be passed to useConfig() | #### Returns @@ -1731,7 +1737,7 @@ Use this React Hook to obtain your module's configuration. #### Defined in -[packages/framework/esm-react-utils/src/useConfig.ts:163](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-react-utils/src/useConfig.ts#L163) +[packages/framework/esm-react-utils/src/useConfig.ts:171](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-react-utils/src/useConfig.ts#L171) ___ diff --git a/packages/framework/esm-react-utils/src/useConfig.test.tsx b/packages/framework/esm-react-utils/src/useConfig.test.tsx index 208a03c7c..86d1c8392 100644 --- a/packages/framework/esm-react-utils/src/useConfig.test.tsx +++ b/packages/framework/esm-react-utils/src/useConfig.test.tsx @@ -20,6 +20,12 @@ function RenderConfig(props) { return ; } +function RenderExternalConfig(props) { + const config = useConfig({ externalModuleName: props.externalModuleName }); + + return ; +} + function clearConfig() { mockConfigInternalStore.resetMock(); } @@ -297,4 +303,40 @@ describe(`useConfig in an extension`, () => { expect(screen.findByText("Yet another thing")).toBeTruthy() ); }); + + it("can optionally load an external module's configuration", async () => { + defineConfigSchema("first-module", { + thing: { + _default: "first thing", + }, + }); + + defineConfigSchema("second-module", { + thing: { + _default: "second thing", + }, + }); + + render( + Suspense!}> + + + + + ); + + await waitFor(() => expect(screen.findByText("second thing")).toBeTruthy()); + }); }); diff --git a/packages/framework/esm-react-utils/src/useConfig.ts b/packages/framework/esm-react-utils/src/useConfig.ts index 6325d13a9..4b95821d4 100644 --- a/packages/framework/esm-react-utils/src/useConfig.ts +++ b/packages/framework/esm-react-utils/src/useConfig.ts @@ -157,16 +157,24 @@ function useNormalConfig(moduleName: string) { return state; } +interface UseConfigOptions { + /** An external module to load the configuration from. This option should only be used if + absolutely necessary as it can end up making frontend modules coupled to one another. */ + externalModuleName?: string; +} + /** * Use this React Hook to obtain your module's configuration. + * + * @param options Additional options that can be passed to useConfig() */ -export function useConfig< - T = Omit ->() { +export function useConfig>(options?: UseConfigOptions) { // This hook uses the config of the MF defining the component. // If the component is used in an extension slot then the slot // may override (part of) its configuration. - const { moduleName, extension } = useContext(ComponentContext); + const { moduleName: contextModuleName, extension } = + useContext(ComponentContext); + const moduleName = options?.externalModuleName ?? contextModuleName; if (!moduleName && !extension) { throw Error(errorMessage); @@ -175,11 +183,11 @@ export function useConfig< const normalConfig = useNormalConfig(moduleName); const extensionConfig = useExtensionConfig(extension); const config = useMemo( - () => ({ - ...normalConfig, - ...extensionConfig, - }), - [normalConfig, extensionConfig] + () => + options?.externalModuleName && moduleName === options.externalModuleName + ? { ...normalConfig } + : { ...normalConfig, ...extensionConfig }, + [moduleName, options?.externalModuleName, normalConfig, extensionConfig] ); return config as T;