React Native使用useEffect加载i18n存储语言时无法更新yesLanguage状态
问题根因
- 你的i18n实例是异步初始化的:i18n文件中直接导出
getDefaultLang()执行返回的Promise,而非初始化完成的i18n实例。App组件加载时i18n还没完成初始化,useTranslation()调用会触发异常,直接打断后续状态更新逻辑,因此setYesLanguage(true)始终没有正常执行。 - 异步操作顺序错误:
changeLanguage方法中的i18n.changeLanguage是异步方法,你直接在调用它之后同步执行setYesLanguage(true),没有等待语言切换完成,即便初始化正常也可能出现页面渲染时语言未加载完成的问题。 - 可选笔误问题:所有存储语言的key都拼写错误,
currentLnaguage应为currentLanguage,只是因为两处都写错了暂时不影响取值,后续维护建议修正。
修复方案
1. 调整i18n文件导出逻辑
不要直接导出异步初始化的Promise,分别导出i18n实例和初始化方法:
import i18n from 'i18next'; import {initReactI18next} from 'react-i18next'; import en from './en/en.json'; import ar from './ar/ar.json'; import he from './he/he.json'; import AsyncStorage from '@react-native-async-storage/async-storage'; export const initI18n = async () => { const storedLang = await AsyncStorage.getItem('currentLanguage'); // 修正拼写错误的key return i18n .use(initReactI18next) .init({ resources: { en: en, ar: ar, he: he }, lng: storedLang ? storedLang : 'ar', interpolation: { escapeValue: false, }, fallbackLng: ['en', 'ar','he'], }); }; export default i18n;
2. 调整App组件逻辑
等待i18n初始化、语言切换全部完成后再更新状态渲染页面:
import React,{useState,useEffect} from 'react'; import i18n, {initI18n} from './translations/i18n'; import {View, Text,Pressable} from 'react-native'; import {useTranslation} from 'react-i18next'; import AsyncStorage from '@react-native-async-storage/async-storage'; import {HomeScreen} from './src/screens/HomeScreen'; import 'intl-pluralrules'; function App(props){ const {t, i18n} = useTranslation(); const [currentLanguage,setLanguage] = useState('ar'); const [yesLanguage , setYesLanguage] = useState(false); const changeLanguage = async (value) => { try { await i18n.changeLanguage(value); setLanguage(value); await AsyncStorage.setItem('currentLanguage',value); } catch(err) { console.log(err); } }; useEffect(()=>{ const init = async () => { await initI18n(); const val = await AsyncStorage.getItem('currentLanguage'); const newDefaultLang = val ? val : "ar"; await changeLanguage(newDefaultLang); setYesLanguage(true); } init(); },[]); return yesLanguage && <HomeScreen buttonTitle={t('ordernow')} deliveryText={t('delivery')} /> }; export default App;
内容的提问来源于stack exchange,提问作者Mikha Matta
相关产品推荐
相关产品推荐

