使用connected-react-router调用push('/')时URL未更新的问题排查
push('/')时URL不更新,其他路由功能正常 我在项目中使用connected-react-router进行路由管理,除调用push('/')的场景外,其余路由功能均正常运行。调用push('/')时,页面URL并未发生变化;若移除路由定义中的exact属性,页面内容会显示为预期的Home组件内容,但URL仍然没有更新。当前项目使用的依赖版本如下:"react-router-dom": "^6.2.1","react": "^17.0.2","connected-react-router": "^6.9.2"。请问可能是什么原因导致该问题?
附配置示例代码:
ReactDOM.render( <React.StrictMode> <Provider store={store}> <OidcProvider store={store} userManager={userManager}> <AppContextProvider> <ThemeProvider theme={theme}> <SnackbarProvider maxSnack={10}> <Layout> <ConnectedRouter history={history}> <Switch> <Route exact path="/" component={Home} /> <Route path="/callback" component={CallbackPage} /> <Route path="/user" component={Users} /> <Route path="/login" component={Login} /> <Route path="/register" component={Register} /> <Route path="/account" component={MyAccount} /> <Route path="/userdetails/:id" component={UserPage} /> </Switch> </ConnectedRouter> </Layout> </SnackbarProvider> </ThemeProvider> </AppContextProvider> </OidcProvider> </Provider> </React.StrictMode>, document.getElementById('root'), );
可能的原因及解决办法
首先最可能的是版本兼容问题——你用的connected-react-router@6.9.2是专门适配react-router v5的,但项目里装的是react-router-dom v6,这俩版本根本不搭!react-router v6做了大量底层改动,比如把Switch换成Routes,路由匹配逻辑也完全重构了,connected-react-router目前对v6的支持并不完善,尤其是根路径的push操作很容易因为内部逻辑冲突导致URL不更新。
解决办法要么把react-router-dom降级到v5.x(比如v5.3.0),和connected-react-router版本匹配;要么干脆换掉connected-react-router,用react-router v6自带的useNavigate钩子配合redux中间件来处理路由状态,或者用@rematch/router这种适配v6的路由管理库。
其次要检查history实例的创建方式:你是不是用了connected-react-router提供的createBrowserHistory?如果是自己单独用history库创建的实例,很可能和connected-react-router的内部状态不同步,导致push('/')只更新了redux状态,没同步到浏览器URL。
解决办法:确保history实例是通过import { createBrowserHistory } from 'connected-react-router'创建的,并且正确注入到store和ConnectedRouter组件里。
还有路由写法不符合v6规范的问题:react-router v6已经移除了Switch组件,换成了Routes,而且Route组件的component属性也改成了element。你现在还在用Switch和component,虽然v6有兼容层,但根路径加上exact后,可能触发了内部的匹配异常,导致URL不更新。
解决办法:按照v6的规范重构路由代码,把Switch换成Routes,component={Home}改成element={<Home />},而且v6默认就是精确匹配根路径,exact属性可以直接删掉。重构后的路由大概是这样:
<ConnectedRouter history={history}> <Routes> <Route path="/" element={<Home />} /> <Route path="/callback" element={<CallbackPage />} /> {/* 其他路由照这个格式改 */} </Routes> </ConnectedRouter>
最后还要检查Redux中间件配置:有没有把connected-react-router的routerMiddleware加入到store的中间件里?如果没加,push操作只会触发redux action,不会真正修改浏览器的history记录。
解决办法:确保store配置里包含这个中间件,示例代码如下:
import { createStore, applyMiddleware, compose } from 'redux'; import { routerMiddleware } from 'connected-react-router'; import rootReducer from './reducers'; import history from './history'; const store = createStore( rootReducer(history), compose( applyMiddleware( routerMiddleware(history), // 这个必须加! // 你项目里的其他中间件比如thunk、saga之类的 ), ), );
内容的提问来源于stack exchange,提问作者radulfr

