在@shopify/react-i18n中切换语言时如何触发页面重新渲染?
问题根因
- 原
TranslateWrapper中未对I18nManager实例做依赖绑定,Context变更无法正确触发消费组件更新 - 自定义
UseI18nHook没有关联Context的最新locale,只会在组件挂载时初始化一次翻译实例,切换语言后不会自动更新 - 业务组件未用
observer包裹,无法响应MobX的状态变更触发重渲染 - 部分版本的
@shopify/react-i18n的useI18n默认不会监听Context实例变化,需要主动传入依赖触发更新
修复步骤
1. 优化TranslateWrapper逻辑
给I18nManager添加useMemo依赖绑定,仅当语言状态变化时才生成新的Manager实例,保证Context变更能正确向下传导:
import React, {useMemo} from "react"; import {inject, observer} from "mobx-react"; import {I18nContext, I18nManager} from '@shopify/react-i18n'; const TranslateWrapper = inject(stores => ({ activeEnglish: stores.LocalizeStore.activeEnglish }))(observer(({activeEnglish, children}) => { // 仅activeEnglish变更时才重新生成Manager实例 const i18nManager = useMemo(() => new I18nManager({ locale: activeEnglish ? 'en' : 'fr', onError(error) { console.log(error); }, }), [activeEnglish]); return( <I18nContext.Provider value={i18nManager}> {children} </I18nContext.Provider> ) })); export default TranslateWrapper;
2. 改造自定义翻译Hook
主动从Context获取最新locale作为useI18n的依赖,保证语言切换时自动重新生成翻译实例:
import {useI18n, useI18nContext} from "@shopify/react-i18n"; import enTrans from "../../translate/en.json"; import frTrans from "../../translate/fr.json"; export const UseI18nHook = () => { // 读取当前Context的Manager实例,获取最新locale const i18nManager = useI18nContext(); const currentLocale = i18nManager.locale; // 将locale作为依赖传入useI18n,变更时自动更新翻译配置 return useI18n({ id: 'App', fallback: 'fr', locale: currentLocale, translations(locale) { return locale === "en" ? enTrans : frTrans; }, }); };
3. 给业务组件添加observer包裹
所有使用UseI18nHook的页面组件必须用observer包裹,才能响应MobX状态变更触发重渲染,拉取最新翻译内容:
import { observer } from 'mobx-react-lite'; import { UseI18nHook } from './你的hook路径'; // 必须用observer包裹组件 const InstallPage = observer(() => { const [i18n] = UseI18nHook(); return <h1>{i18n.translate('App.InstallPage.installTitle')}</h1> }); export default InstallPage;
4. 校验MobX Store响应式配置
确认你的LocalizeStore里的activeEnglish属性已经被标记为响应式:
import { makeAutoObservable } from 'mobx'; class LocalizeStore { activeEnglish = false; constructor() { // 必须调用makeAutoObservable标记属性为响应式 makeAutoObservable(this); } toggleLanguage = () => { this.activeEnglish = !this.activeEnglish; } } export const localizeStore = new LocalizeStore();
可选兜底方案
如果以上步骤做完还有偶发不更新的情况,可以在路由根容器上加和locale绑定的key,语言切换时强制重渲染整个路由树:
// App根组件代码 const App = () => { const activeEnglish = localizeStore.activeEnglish; const currentLocale = activeEnglish ? 'en' : 'fr'; return ( <TranslateWrapper> {/* key随locale变化时自动重渲染所有子组件 */} <Routes key={currentLocale}> {/* 你的路由配置 */} </Routes> </TranslateWrapper> ) }
内容的提问来源于stack exchange,提问作者ugar2000
相关产品推荐
相关产品推荐

