React Router:登录验证后重定向至受限路由及历史回退问题
我来帮你搞定这两个React Router的问题,结合你的场景和代码一步步讲明白:
其实很简单,React Router的history对象是基于浏览器原生的window.history封装的,你直接用window.history.go(-2)就能实现回退两页的需求,而且这个操作不会修改历史记录栈——它只是在现有历史栈里向后导航两步。举个例子:用户从页面A→B→C,调用go(-2)后会回到A,历史栈里依然保留A、B、C,之后用户点浏览器的前进按钮还能回到B和C,完全符合你“保留历史记录”的要求。
如果只是回退一页,用history.goBack()也可以,但回退多页就用go()方法传负数参数就行。
先说说你现有代码里的小问题:你用了window.history.go(-2)来跳转,但这个方法依赖历史栈的长度,场景很受限——比如如果用户不是从/account/dashboard直接进入登录流程,而是直接打开/login或者/verify-otp,那go(-2)可能会跳到错误的页面,甚至回到空白页。
咱们用React Router的标准做法来解决,分两步:
第一步:拦截受限路由时保存原目标路径
在你的私有路由(也就是管控/account/dashboard这类受限页面的路由组件)里,把用户原本要访问的路径存在跳转的state里,再重定向到登录页。比如:
const PrivateRoute = ({ component: Component, ...rest }) => { const { isSignedIn } = useSelector(state => state.user); return ( <Route {...rest} render={props => isSignedIn ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: "/login", state: { from: props.location } // 把原路径存在state中 }} /> ) } /> ); };
这样不管用户要访问哪个受限页面,咱们都把目标路径记下来了。
第二步:验证成功后读取state跳回原路径
修改你verifyOTP代码里的最后一个else分支,把原来的window.history.go(-2)替换成读取state里的原路径再跳转:
} else { // 从history的state里获取登录前的目标路径,默认跳首页 const targetPath = history.location.state?.from?.pathname || '/'; history.push(targetPath); }
这里要注意:如果你的history是通过useHistory hook或者Redux connect获取的React Router历史对象,那history.location.state就能拿到咱们之前存在的from信息。这样不管用户是从哪个受限页面过来的,都能精准跳回去,完全避免了go(-2)的不确定性问题。
内容的提问来源于stack exchange,提问作者Fahad Sohail

