如何在SSR中获取react-router-redux的<Redirect>跳转URL?
解决react-router-redux@5.0.0-alpha.9 SSR中捕获跳转的问题
我完全懂你遇到的这个痛点——在服务端渲染场景下,<Redirect>的跳转只在浏览器端生效,服务端根本抓不到这个跳转动作,没法主动发起302重定向。那个版本的ConnectedRouter确实没有像StaticRouter那样内置context参数,但我们可以利用react-router-redux和Redux Store的联动特性来解决这个问题。
核心思路
react-router-redux会把所有路由操作(包括<Redirect>触发的跳转)转换成Redux Action,同步更新Store里的路由状态。所以我们只需要在服务端渲染完成后,对比Store中的路由状态和初始请求URL,就能判断是否发生了跳转,进而提取目标URL。
具体实现步骤
1. 初始化Memory History和Redux Store
首先创建服务端专用的Memory History,再初始化带路由中间件的Redux Store,确保路由状态能和Store同步:
import { ConnectedRouter, routerMiddleware } from 'react-router-redux'; import createHistory from 'history/createMemoryHistory'; import { Provider } from 'react-redux'; import { renderToString } from 'react-dom/server'; import { createStore, applyMiddleware } from 'redux'; import rootReducer from './reducers'; // 你的根reducer // 基于当前请求URL初始化Memory History const history = createMemoryHistory({ initialEntries: [req.url], initialIndex: 0, }); // 创建包含路由中间件的Store,初始路由状态和请求URL保持一致 const store = createStore( rootReducer, { router: { location: history.location, action: 'POP' } }, applyMiddleware(routerMiddleware(history)) );
2. 渲染组件并检查跳转状态
同步渲染完成后,直接对比Store中的路由URL和初始请求URL,不一致就说明发生了<Redirect>跳转:
// 把组件渲染成HTML字符串 const appHtml = renderToString( <Provider store={store}> <ConnectedRouter history={history}> <Application /> </ConnectedRouter> </Provider> ); // 从Store中取出当前路由状态 const { router } = store.getState(); const currentRouteUrl = router.location.pathname + router.location.search; // 判断是否发生了跳转 if (currentRouteUrl !== req.url) { // 发起302重定向到目标URL res.writeHead(302, { Location: currentRouteUrl }); res.end(); return; } // 没有跳转的话,返回渲染好的页面 res.send(` <!DOCTYPE html> <html> <head> <title>SSR App</title> </head> <body> <div id="root">${appHtml}</div> <!-- 加载客户端脚本完成hydration --> <script src="/client-bundle.js"></script> </body> </html> `);
为什么history.listen没触发?
在SSR的同步渲染流程里,react-router-redux是通过Redux中间件同步History和Store状态的,history.listen的回调不会在同步渲染过程中触发(History的更新逻辑是绑定在Redux Action的处理流程里的),所以直接监听Store状态才是最可靠的方式。
额外注意事项
- 确保你的认证逻辑能在服务端执行:比如判断用户是否登录的逻辑要在SSR阶段运行,这样
<Redirect>才会在服务端渲染时被触发。 - 不管
<Redirect>用的是push还是默认的replace,我们只需要对比URL即可,不需要区分动作类型。 - 初始Store的
router状态要和请求URL严格一致,避免出现误判。
内容的提问来源于stack exchange,提问作者Sergio Toro
相关产品推荐
相关产品推荐

