升级React-Redux适配React18后,使用createRoot导致Redux失效
React18 createRoot下Redux失效的解决方案(混合类/函数组件场景)
问题根源
React18的createRoot启用了并发渲染模式,而React-Redux 8.x对该模式有明确适配要求。你的项目混合使用类组件(connect/mapToProps)和函数组件(useSelector),旧的Redux配置或组件写法可能不符合新渲染模式的规则,导致组件无法正确获取或响应Redux状态更新。
具体解决步骤
1. 切换到configureStore创建Redux Store
React-Redux 8.x推荐配合@reduxjs/toolkit的configureStore创建store,它默认集成redux-thunk,并做了并发模式下的适配优化,比旧的createStore更稳定。
替换旧的store创建代码:
// 旧写法(不推荐) import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; const store = createStore(rootReducer, applyMiddleware(thunk));
改为:
// 新写法(推荐) import { configureStore } from '@reduxjs/toolkit'; import rootReducer from './reducers'; const store = configureStore({ reducer: rootReducer, // redux-thunk已默认集成,无需额外配置 });
2. 确保Provider正确包裹根组件
必须让createRoot渲染的根组件被Provider直接包裹,不能将Provider放在App内部深层,否则组件无法正确获取store上下文。
正确示例:
import { createRoot } from 'react-dom/client'; import React from 'react'; import App from './App'; import { Provider } from 'react-redux'; import store from './store'; const root = createRoot(document.getElementById('root')); root.render( <Provider store={store}> <App /> </Provider> );
3. 修复类组件的connect用法
- 确保
mapToProps是纯函数:只依赖state和ownProps,不在内部执行异步操作、修改外部变量等副作用。 - 避免手动设置
pure: false:并发模式下非纯组件容易出现渲染异常,保持默认的pure: true即可;若必须关闭,需确保组件的props变化逻辑完全可控。
4. 优化函数组件的useSelector
- 选择器必须是纯函数:不能返回不稳定的引用(比如每次渲染创建新对象/数组),否则会导致不必要的重渲染,甚至并发模式下的状态异常。
- 引用类型数据使用
shallowEqual比较:
import { useSelector, shallowEqual } from 'react-redux'; // 错误:每次返回新对象,触发不必要重渲染 // const user = useSelector(state => ({ name: state.user.name, age: state.user.age })); // 正确:用shallowEqual比较引用类型 const user = useSelector(state => state.user, shallowEqual); // 或者拆分选择器(更推荐) const userName = useSelector(state => state.user.name); const userAge = useSelector(state => state.user.age);
5. 排查第三方中间件/Enhancer兼容性
如果项目使用了自定义或第三方Redux中间件,检查其是否适配React18并发模式。旧的中间件可能依赖同步渲染的假设,导致状态更新异常。优先使用@reduxjs/toolkit提供的官方中间件,或升级第三方中间件到最新版本。
6. 开启严格模式排查隐藏问题
React18的严格模式会在开发模式下执行两次渲染,帮助检测非纯函数、副作用等问题。虽然你当前没有看到错误,但开启后可能暴露隐藏的问题:
root.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> );
内容的提问来源于stack exchange,提问作者Noriller
相关产品推荐
相关产品推荐

