From 3f483ff32a84473b55b84ac383c49758b4ba2b23 Mon Sep 17 00:00:00 2001 From: zakudriver Date: Thu, 5 Dec 2024 16:45:13 +0800 Subject: [PATCH] feat: Rendering pages on browser when Instance i18n finished initialization completely Rendering pages after loading resources of backend to resolve error `Text content does not match server-rendered HTML` on NEXT. --- src/appWithTranslation.tsx | 28 ++++++++++++++++++++++------ src/types.ts | 1 + 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/appWithTranslation.tsx b/src/appWithTranslation.tsx index 3d1089f3..e816bba9 100644 --- a/src/appWithTranslation.tsx +++ b/src/appWithTranslation.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useRef } from 'react' +import React, { useMemo, useState, useRef } from 'react' import hoistNonReactStatics from 'hoist-non-react-statics' import { I18nextProvider } from 'react-i18next' import type { AppProps as NextJsAppProps } from 'next/app' @@ -18,11 +18,18 @@ export { export let globalI18n: I18NextClient | null = null -const addResourcesToI18next = (instance: I18NextClient, resources: Resource) => { +const addResourcesToI18next = ( + instance: I18NextClient, + resources: Resource +) => { if (resources && instance.isInitialized) { for (const locale of Object.keys(resources)) { for (const ns of Object.keys(resources[locale])) { - if (!instance?.store?.data || !instance.store.data[locale] || !instance.store.data[locale][ns]) { + if ( + !instance?.store?.data || + !instance.store.data[locale] || + !instance.store.data[locale][ns] + ) { instance.addResourceBundle( locale, ns, @@ -49,6 +56,9 @@ export const appWithTranslation = ( const ns = _nextI18Next?.ns const instanceRef = useRef(null) + const [ready, setReady] = useState( + !configOverride?.clientAwaitInit + ) /** * Memoize i18n instance and reuse it rather than creating new instance. @@ -89,7 +99,7 @@ export const appWithTranslation = ( if (instance) { addResourcesToI18next(instance, resources) } else { - instance = createClient({ + const { i18n: ins, initPromise } = createClient({ ...createConfig({ ...userConfig, lng: locale, @@ -97,7 +107,13 @@ export const appWithTranslation = ( lng: locale, ...(ns && { ns }), resources, - }).i18n + }) + + instance = ins + + if (configOverride?.clientAwaitInit) { + initPromise.then(() => setReady(true)) + } addResourcesToI18next(instance, resources) @@ -117,7 +133,7 @@ export const appWithTranslation = ( i18n.changeLanguage(locale) }, [i18n, locale]) - return i18n !== null ? ( + return i18n !== null && ready ? ( diff --git a/src/types.ts b/src/types.ts index 8744c77b..c22aa338 100644 --- a/src/types.ts +++ b/src/types.ts @@ -49,6 +49,7 @@ export type UserConfig = { reloadOnPrerender?: boolean serializeConfig?: boolean use?: any[] + clientAwaitInit?: boolean } & InitOptions export type InternalConfig = Omit &