React Router通过<Link>跳转正常但地址栏输入URL不生效如何解决?
问题原因
- BrowserRouter的服务端适配缺失。你使用的
BrowserRouter基于HTML5 History API实现前端路由,<Link>跳转是纯前端修改地址栏、触发路由逻辑,不会请求服务器;但直接在地址栏输入URL或者刷新页面时,浏览器会先向服务器发起对应路径的资源请求,如果服务器没有配置「所有路径都fallback到index.html」的规则,服务器找不到对应路径的静态资源,会直接返回404,根本不会加载到你的前端路由代码。 - Switch组件使用错误。Switch的特性是只会匹配第一个符合条件的直接子
<Route>/<Redirect>,但你把<App>、<TransitionGroup>作为了Switch的直接子元素,导致Switch的路由匹配逻辑完全失效,通配路由的重定向规则也不会按预期触发。 - 通配路由配置错误。你给
path="*"的通配路由加了exact精确匹配属性,而通配符路由本身是匹配所有未命中的路径,加exact会导致匹配失效。另外你自定义路由都拼接了process.env.PUBLIC_URL,但Redirect的to属性直接写死了"/",如果项目有部署二级路径的需求,这里会出现跳转路径不匹配的问题。
解决方案
- 配置服务端fallback规则
不同部署环境配置方式不同,常见场景配置如下:- 本地用create-react-app启动的开发服务默认已适配,无需修改
- Nginx部署:在nginx站点配置中添加
try_files $uri $uri/ /index.html; - Apache部署:在根目录添加.htaccess文件配置重写规则,所有请求指向index.html
- 静态站点托管平台部署:找到「自定义错误页」或「路由 fallback」配置项,将404响应指向index.html即可
- 修正Switch的子元素结构
把<App>、<TransitionGroup>移到<Switch>外层,保证Switch的直接子元素只有<Route>和<Redirect>,修正后参考代码:
return( <Fragment> <BrowserRouter basename={process.env.PUBLIC_URL}> <App> <TransitionGroup> <Switch> {routes.map(({ path, Component }) => ( <Route key={path} exact path={path}> {({ match }) => ( <CSSTransition in={match != null} timeout={100} classNames={anim} unmountOnExit> <div><Component/></div> </CSSTransition> )} </Route> ))} <Route path="*"><Redirect to={`/`}/></Route> </Switch> </TransitionGroup> </App> </BrowserRouter> </Fragment> )
- 修正冗余配置
删掉通配路由的exact属性,同时把BrowserRouter的basename统一设为process.env.PUBLIC_URL,不需要再给每个Route的path单独拼接PUBLIC_URL,保持路径配置统一。
内容的提问来源于stack exchange,提问作者mathijng
相关产品推荐
相关产品推荐

