未认证用户登录页无效URL拦截跳转及路由冲突问题解决
解决React路由拦截无效URL及有效路由失效问题
你遇到的核心问题是Switch路由的匹配顺序错误,导致NoMatch组件提前拦截了所有未被前面两个Route匹配的路径,后面的有效路由根本没机会被渲染。另外还需要实现未认证用户访问无效URL时跳转到登录页的需求,我们一步步来解决:
1. 调整路由匹配顺序
Switch组件会按照代码中路由的顺序依次匹配,一旦找到符合条件的路由就停止匹配。所以你需要把NoMatch路由放在所有有效路由的最后面,这样才不会影响正常路由的渲染:
修改index.js中的Switch部分:
<Switch> <Route exact path="/" render={() => { if(!store.getState().login.isAvailable) { return <Redirect to="/login"/> } else { return <Redirect to="/dashboard" /> } }} /> <Route exact path="/login" component={Login} /> {/* 先渲染所有业务相关的有效路由 */} {Routes.map((prop, key) => { return <Route path={prop.path} key={key} component={prop.component} />; })} {/* 最后才渲染404路由,仅当前面没有匹配到任何有效路由时才触发 */} <Route component={NoMatch} /> </Switch>
2. 修改NoMatch组件,添加认证判断
现在需要在NoMatch组件中检查用户是否已认证:如果未认证,就重定向到登录页;如果已认证,再显示404提示。
推荐使用React-Redux的connect来获取登录状态(比直接访问store更符合最佳实践),修改NoMatch.jsx:
import React from 'react' import { withRouter, Redirect } from 'react-router-dom'; import { connect } from 'react-redux'; const NoMatch = ({ location, isAuthenticated }) => { // 未认证用户访问无效URL,跳转到登录页 if (!isAuthenticated) { return <Redirect to="/login" />; } // 已认证用户显示404提示 return ( <div> <h3>No match for <code>{location.pathname}</code></h3> </div> ); } // 从Redux store中获取登录状态 const mapStateToProps = state => ({ isAuthenticated: state.login.isAvailable }); // 先connect注入状态,再用withRouter包装获取location export default withRouter(connect(mapStateToProps)(NoMatch));
额外注意事项
- 你的
routes/index.js中Dashboard的path是"/",而根路径已经有一个exact的Route做重定向,所以不会有冲突,但如果后续需要添加其他根路径下的子路由,建议把Dashboard的path改成"/dashboard",避免路由匹配混乱。 - 如果Dashboard内部有子路由,确保在Dashboard组件中使用
Switch和Route来处理,并且不要忘记在根路由中给Dashboard的Route保留默认的exact={false},这样子路由才能正常匹配。
内容的提问来源于stack exchange,提问作者Ashwat Acharya
相关产品推荐
相关产品推荐

