使用Redux时React-Router失效问题求助
这种情况我碰到过好多次,通常是组件没有正确响应Redux状态变化或者路由配置的小细节没做好,给你几个排查方向:
1. 确认路由组件是否被connect正确包裹
如果你的路由组件依赖Redux状态,一定要确保它被connect()高阶组件包裹。要是组件没订阅Redux的store变化,哪怕URL改了,组件也不会触发重新渲染。
举个反例:
// 错误示例:路由组件没被connect包裹 const HomePage = () => { return <div>Home</div>; }; // 正确示例:哪怕不需要映射state/dispatch,也要传空对象用connect包裹 const ConnectedHomePage = connect()(HomePage); // 路由中使用包裹后的组件 <Route path="/home" component={ConnectedHomePage} />
2. 检查reducer是否返回了新的状态对象
Redux的reducer必须是纯函数,每次更新状态必须返回新对象,不能直接修改原对象。要是reducer直接改了原state,组件检测不到状态变化,自然不会重新渲染。
错误示例:
// 错误:直接修改原state const rootReducer = (state = initialState, action) => { switch(action.type) { case 'UPDATE_DATA': state.user = action.payload; return state; default: return state; } };
正确示例:
// 正确:返回新的状态对象 const rootReducer = (state = initialState, action) => { switch(action.type) { case 'UPDATE_DATA': return { ...state, user: action.payload }; default: return state; } };
3. 避免使用PureComponent时忽略路由props
如果你的路由组件继承了PureComponent,要注意路由相关的props(比如match、location)是否被正确处理。PureComponent会做浅比较props,要是路由变化但组件的props看起来没变化(比如没把location传给组件),它就不会重新渲染。
解决办法:要么把location作为props传给组件,要么改用普通的Component,或者在connect的mapStateToProps里加入location:
const mapStateToProps = (state, ownProps) => { return { user: state.user, location: ownProps.location // 加入location,确保路由变化时触发更新 }; }; const ConnectedHomePage = connect(mapStateToProps)(HomePage);
4. 确认路由的包裹层级是否正确
要保证Router组件是被Provider组件包裹在内部的,这样路由组件才能访问到Redux的store。正确的嵌套顺序应该是:
// 正确的组件嵌套结构 ReactDOM.render( <Provider store={store}> <BrowserRouter> <App /> </BrowserRouter> </Provider>, document.getElementById('root') );
要是把Provider放在Router里面,路由组件可能没法正确获取store,导致状态更新不触发渲染。
5. 检查是否需要使用withRouter高阶组件
如果你的组件不是直接作为Route的component或render属性传入,而是嵌套在其他组件里面,可能需要用withRouter来注入路由相关的props,确保组件能感知到路由变化。
比如:
import { withRouter } from 'react-router-dom'; // 这个组件嵌套在某个路由组件内部 const Navigation = ({ location }) => { return <Link to="/home">Home</Link>; }; // 用withRouter包裹,注入location等路由props const ConnectedNavigation = withRouter(Navigation);
你可以按上面的顺序逐一排查,大部分情况都是其中某个细节没处理好导致的。
内容的提问来源于stack exchange,提问作者Arijit

