From c3ef6060afcaba0c5561b58abac6142e8bdbec2a Mon Sep 17 00:00:00 2001 From: github-automation-metabase <166700802+github-automation-metabase@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:37:38 -0500 Subject: [PATCH] fix(sdk): remove `Cannot update a component XX while rendering a (#50078) (#50084) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(sdk): remove `Cannot update a component XX while rendering a different component` error * test(sdk): introduce jest test to make sure api.basename is set before loading the locale Co-authored-by: Nicolò Pretto <info@npretto.com> --- .../hooks/private/use-init-data.ts | 12 ++++-- .../test/auth-flow.unit.spec.tsx | 42 ++++++++++++++++--- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/enterprise/frontend/src/embedding-sdk/hooks/private/use-init-data.ts b/enterprise/frontend/src/embedding-sdk/hooks/private/use-init-data.ts index 290bc636359..b682bc6e2a2 100644 --- a/enterprise/frontend/src/embedding-sdk/hooks/private/use-init-data.ts +++ b/enterprise/frontend/src/embedding-sdk/hooks/private/use-init-data.ts @@ -1,4 +1,4 @@ -import { useRef } from "react"; +import { useEffect, useRef } from "react"; import { useMount } from "react-use"; import _ from "underscore"; @@ -37,9 +37,13 @@ export const useInitData = ({ config }: InitDataLoaderParameters) => { if (api.basename !== config.metabaseInstanceUrl) { api.basename = config.metabaseInstanceUrl; } - if (config.fetchRequestToken !== fetchRefreshTokenFnFromStore) { - dispatch(setFetchRefreshTokenFn(config.fetchRequestToken ?? null)); - } + + useEffect(() => { + if (config.fetchRequestToken !== fetchRefreshTokenFnFromStore) { + // This needs to be a useEffect to avoid the `Cannot update a component XX while rendering a different component` error + dispatch(setFetchRefreshTokenFn(config.fetchRequestToken ?? null)); + } + }, [config.fetchRequestToken, fetchRefreshTokenFnFromStore, dispatch]); useMount(() => { if (hasBeenInitialized.current) { diff --git a/enterprise/frontend/src/embedding-sdk/test/auth-flow.unit.spec.tsx b/enterprise/frontend/src/embedding-sdk/test/auth-flow.unit.spec.tsx index 439528e97d2..4af42646cc9 100644 --- a/enterprise/frontend/src/embedding-sdk/test/auth-flow.unit.spec.tsx +++ b/enterprise/frontend/src/embedding-sdk/test/auth-flow.unit.spec.tsx @@ -34,12 +34,19 @@ const MOCK_SESSION = { const MOCK_CARD = createMockCard({ id: 1 }); -const setup = (sdkConfig: SDKConfig) => { +const setup = ({ + sdkConfig, + locale, +}: { + sdkConfig: SDKConfig; + locale?: string; +}) => { return render( <MetabaseProvider config={{ ...sdkConfig, }} + locale={locale} > <StaticQuestion questionId={1} /> </MetabaseProvider>, @@ -51,7 +58,7 @@ const getLastAuthProviderApiCall = () => fetchMock.lastCall(AUTH_PROVIDER_URL); const getLastCardQueryApiCall = () => fetchMock.lastCall(`${METABASE_INSTANCE_URL}/api/card/${MOCK_CARD.id}/query`); -describe("SDK auth flow", () => { +describe("SDK auth and init flow", () => { beforeEach(() => { fetchMock.reset(); fetchMock.get(AUTH_PROVIDER_URL, { @@ -79,7 +86,7 @@ describe("SDK auth flow", () => { authProviderUri: AUTH_PROVIDER_URL, }); - const { rerender } = setup(sdkConfig); + const { rerender } = setup({ sdkConfig }); expect(fetchMock.calls(AUTH_PROVIDER_URL)).toHaveLength(1); @@ -111,7 +118,7 @@ describe("SDK auth flow", () => { authProviderUri: AUTH_PROVIDER_URL, }); - setup(sdkConfig); + setup({ sdkConfig }); await waitForRequest(() => getLastAuthProviderApiCall()); expect(getLastAuthProviderApiCall()![1]).toMatchObject({ @@ -142,7 +149,7 @@ describe("SDK auth flow", () => { fetchRequestToken: customFetchFunction, }); - setup(sdkConfig); + setup({ sdkConfig }); expect(customFetchFunction).toHaveBeenCalledWith(AUTH_PROVIDER_URL); @@ -169,7 +176,7 @@ describe("SDK auth flow", () => { apiKey: MOCK_API_KEY, }); - setup(sdkConfig); + setup({ sdkConfig }); await waitForRequest(() => getLastUserApiCall()); expect(getLastUserApiCall()![1]).toMatchObject({ @@ -187,4 +194,27 @@ describe("SDK auth flow", () => { }); }); }); + + describe("locale", () => { + it("should load the locale from the correct url", () => { + const metabaseInstanceUrl = "http://metabase:3000"; + + // This can happen if the request is made before api.basename is set + const wrongPath = "/app/locales/de.json"; + const correctPath = `${metabaseInstanceUrl}/app/locales/de.json`; + + fetchMock.get(wrongPath, 200); + fetchMock.get(correctPath, 200); + + const sdkConfig = defineEmbeddingSdkConfig({ + metabaseInstanceUrl: metabaseInstanceUrl, + apiKey: MOCK_API_KEY, + }); + + setup({ sdkConfig, locale: "de" }); + + expect(fetchMock.calls(wrongPath)).toHaveLength(0); + expect(fetchMock.calls(correctPath)).toHaveLength(1); + }); + }); }); -- GitLab