Spring Boot+React集成i18next报错:无法读取'useMemo'属性
问题:React集成i18next时添加I18nextProvider出现useMemo读取null错误
在Spring Boot+React项目中集成i18next实现国际化,只要在App.js或其他位置添加I18nextProvider,就会触发以下错误:
scheduler.production.min.js:13 TypeError: Cannot read properties of null (reading 'useMemo') at t.useMemo (react.production.min.js:26:48) at me (I18nextProvider.js:8:17) at gi (react-dom.production.min.js:160:137) at Cs (react-dom.production.min.js:289:337) at bu (react-dom.production.min.js:279:389) at vu (react-dom.production.min.js:279:320) at gu (react-dom.production.min.js:279:180) at au (react-dom.production.min.js:270:88) at ou (react-dom.production.min.js:267:429) at E (scheduler.production.min.js:13:203)
错误出现后翻译文件能正常下载,但页面最终显示空白。怀疑是I18nextProvider重复或多次初始化导致,报错后功能看似正常。
相关代码
i18n初始化代码
import i18n from 'i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import I18NextHttpBackend from 'i18next-http-backend'; import { initReactI18next } from 'react-i18next'; i18n // 从服务器加载翻译文件 .use(I18NextHttpBackend) // 自动检测用户语言 .use(LanguageDetector) // 关联react-i18next .use(initReactI18next) // 初始化配置 .init({ debug: true, fallbackLng: 'en', react: { useSuspense: true }, initImmediate: false }) export default i18n;
Index.js片段
const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <PrimeReactProvider> <CookiesProvider> <I18nextProvider i18n={i18n}> <Suspense fallback="...is loading"> <App /> </Suspense> </I18nextProvider> </CookiesProvider> </PrimeReactProvider> </React.StrictMode> );
App组件代码
const App = () => { useEffect(() => { fetch('/csrf-token') .then(response => response.json()) .then(data => { localStorage.setItem('csrfToken', data.token); localStorage.setItem('csrfHeader', data.headerName); }) .catch(error => console.error('Error fetching CSRF token:', error)); }, []); const router = createBrowserRouter( createRoutesFromElements( <Route> <Route path="/" element={<KineNavBar/>} /> <Route path="/serviceproviders" element={<ServiceProviderSearch/>}/> <Route path='/serviceproviders/:id' element={<ServiceProviderEdit/>}/> </Route> ) ); return (<RouterProvider router={router} />); }
解决方案
1. 检查版本兼容性
该错误通常由react-i18next与React版本不匹配导致,比如高版本react-i18next要求React 18+,低版本React会触发Hook调用异常。
- 执行
npm list react react-i18next查看版本,对照react-i18next版本要求调整到匹配版本。
2. 避免重复嵌套I18nextProvider
检查项目中是否在其他位置(如路由组件、全局Provider)重复渲染了I18nextProvider,导致i18n实例多次初始化。
- 确保整个应用只有一个
I18nextProvider,保持在Index.js的最外层包裹位置。
3. 调整i18n初始化配置
尝试修改初始化选项,调整useSuspense或initImmediate:
.init({ debug: true, fallbackLng: 'en', react: { useSuspense: false // 关闭Suspense,改用手动等待初始化 }, initImmediate: true // 恢复默认,让i18n立即初始化 })
关闭useSuspense后,需在App组件中等待i18n初始化完成再渲染:
const App = () => { const [isI18nReady, setIsI18nReady] = useState(false); useEffect(() => { // 监听i18n初始化完成事件 i18n.on('initialized', () => setIsI18nReady(true)); // 原有CSRF请求逻辑 fetch('/csrf-token') .then(response => response.json()) .then(data => { localStorage.setItem('csrfToken', data.token); localStorage.setItem('csrfHeader', data.headerName); }) .catch(error => console.error('Error fetching CSRF token:', error)); }, []); if (!isI18nReady) return <div>Loading...</div>; const router = createBrowserRouter( createRoutesFromElements( <Route> <Route path="/" element={<KineNavBar/>} /> <Route path="/serviceproviders" element={<ServiceProviderSearch/>}/> <Route path='/serviceproviders/:id' element={<ServiceProviderEdit/>}/> </Route> ) ); return (<RouterProvider router={router} />); }
4. 排查React.StrictMode影响
React严格模式会触发组件双重渲染,可能导致i18n初始化异常。可暂时移除<React.StrictMode>包裹,若错误消失,再调整i18n初始化逻辑避免重复执行问题。
内容的提问来源于stack exchange,提问作者Oddbjornik
相关产品推荐
相关产品推荐

