react-cookies的useCookies引发React无限渲染循环问题
问题描述
更新所有依赖库后,App组件出现持续渲染的无限循环,React抛出Minified React error #185错误。注释掉const [cookies] = useCookies([AUTHENTICATION_COOKIE]);后循环停止,但需要在应用启动时检查cookie。
相关代码:
import React from 'react'; import { CookiesProvider, useCookies } from 'react-cookie'; import { withTranslation } from 'react-i18next'; import { connect } from 'react-redux'; import store from './redux/store'; import { getUserDetailsByToken } from './redux/actions/user-actions'; const AUTHENTICATION_COOKIE = 'authat'; function App(props) { const { i18n, userDetailsLoaded } = props; const [cookies] = useCookies([AUTHENTICATION_COOKIE]); if (cookies[AUTHENTICATION_COOKIE] && !userDetailsLoaded) { store.dispatch(getUserDetailsByToken()); } i18n.changeLanguage('en'); return ( <CookiesProvider> <div className="app"> <Header /> <main className="app-content full-height"> ... </main> </div> </CookiesProvider> ); } function mapStateToProps(state) { return { userDetailsLoaded: state.userReducers.userDetailsLoaded, }; } export default connect(mapStateToProps)(App);
解决方案
1. 修正CookiesProvider的位置
当前useCookies在CookiesProvider外部调用,违反了react-cookie的使用规则——必须在CookiesProvider上下文内使用useCookies。更新依赖后该问题被严格校验,直接触发无限渲染。
需要把CookiesProvider移到App组件外层,比如在入口文件(如index.js)中包裹App:
// index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import { CookiesProvider } from 'react-cookie'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <CookiesProvider> <App /> </CookiesProvider> );
同时移除App组件return中的CookiesProvider。
2. 避免每次渲染都执行语言切换
i18n.changeLanguage('en')在组件每次渲染时都会执行,会触发组件重新渲染,形成循环。用useEffect包裹,只在组件挂载时执行一次:
import React, { useEffect } from 'react'; function App(props) { const { i18n, userDetailsLoaded, dispatch } = props; const [cookies] = useCookies([AUTHENTICATION_COOKIE]); useEffect(() => { i18n.changeLanguage('en'); }, [i18n]); // 其他逻辑 }
3. 正确处理Redux dispatch逻辑
不要直接调用store.dispatch,改用connect注入的dispatch,并把dispatch逻辑放到useEffect中,避免每次渲染都触发:
useEffect(() => { if (cookies[AUTHENTICATION_COOKIE] && !userDetailsLoaded) { dispatch(getUserDetailsByToken()); } }, [cookies, userDetailsLoaded, dispatch]);
完整修复后的App组件代码
import React, { useEffect } from 'react'; import { useCookies } from 'react-cookie'; import { withTranslation } from 'react-i18next'; import { connect } from 'react-redux'; import { getUserDetailsByToken } from './redux/actions/user-actions'; const AUTHENTICATION_COOKIE = 'authat'; function App(props) { const { i18n, userDetailsLoaded, dispatch } = props; const [cookies] = useCookies([AUTHENTICATION_COOKIE]); useEffect(() => { i18n.changeLanguage('en'); }, [i18n]); useEffect(() => { if (cookies[AUTHENTICATION_COOKIE] && !userDetailsLoaded) { dispatch(getUserDetailsByToken()); } }, [cookies, userDetailsLoaded, dispatch]); return ( <div className="app"> <Header /> <main className="app-content full-height"> ... </main> </div> ); } function mapStateToProps(state) { return { userDetailsLoaded: state.userReducers.userDetailsLoaded, }; } export default connect(mapStateToProps)(withTranslation()(App));
内容的提问来源于stack exchange,提问作者Cosmin Glodean
相关产品推荐
相关产品推荐

