React路由刷新或手动输入URL时出现404问题排查咨询
React Router 6刷新/手动输入URL出现404问题分析与解决
问题现象
- 从首页导航到博客文章页面时,内容能正常加载
- 手动输入文章URL或刷新页面时,直接出现404页面未找到错误
- 旧版本React Router项目无需SSR即可正常运行,升级到React Router 6后出现该问题
问题根源
这个问题的核心是客户端路由和静态服务器的匹配逻辑冲突:
- React Router属于客户端路由,页面跳转都是在浏览器端完成,不会向服务器发起新的资源请求
- 当手动输入URL或刷新页面时,浏览器会直接向服务器请求该路径对应的物理文件,但静态服务器(比如Nginx、create-react-app的开发服务器)找不到对应文件,就会返回404
- 旧版本能正常运行,并不是因为路由本身的差异,而是旧项目的服务器配置了SPA fallback规则:无论请求什么路径,都返回项目的
index.html,让客户端路由接管后续的路由匹配工作
新旧版本路由配置差异
旧版本(React Router <6)
使用Switch组件做路由匹配,所有路由都是平级挂载在根路由下:
class App extends Component { render() { return ( <React.Fragment> <Router> <Header /> <Switch> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/coming-soon" component={ComingSoon} /> <Route path="/posts/:id" render={props => <IndividualPost {...props} />} /> </Switch> <Footer /> </Router> </React.Fragment> ); } } export default App;
Switch会按顺序匹配第一个符合条件的路由- 所有路由直接定义在根路由下,没有嵌套层级结构
新版本(React Router 6)
使用createBrowserRouter+RouterProvider的新方式,采用嵌套路由结构:
const router = createBrowserRouter( createRoutesFromElements( <Route path='/' element={<RootLayout/>}> <Route index element ={<Home />}/> <Route path="about" element={<About />}/> <Route path="posts" > <Route index loader={blogsLoader} element={<Blogs/>} /> <Route path="/posts/:id" element={<Post />} /> </Route> </Route> ) ) class App extends Component { render(){ return ( <ChakraProvider > <RouterProvider router={router} /> </ChakraProvider> ); } }
- 用嵌套路由组织页面结构,更符合现代SPA的页面层级逻辑
- 这里的
/posts/:id用了绝对路径,虽然不影响匹配,但不符合嵌套路由的规范,建议改成相对路径path=":id" - React Router 6的路由匹配逻辑更严谨,但这不是导致404的直接原因
解决方案(无需SSR)
解决这个问题根本不需要SSR,只需要给服务器配置SPA fallback规则即可:
1. 开发环境(create-react-app)
create-react-app默认已经配置了fallback规则,如果开发环境仍出现404,检查是否是路由配置的拼写错误,比如嵌套路由的路径定义问题。
2. 生产环境
Nginx配置
在Nginx的站点配置中添加try_files指令,让所有请求都返回index.html:
location / { try_files $uri $uri/ /index.html; }
静态托管平台(Netlify/Vercel等)
- Netlify:在项目根目录创建
_redirects文件,内容如下:/* /index.html 200 - Vercel:在项目根目录创建
vercel.json文件,内容如下:{ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] }
路由配置优化(可选)
把嵌套路由中的绝对路径改成相对路径,让路由结构更清晰:
<Route path="posts" > <Route index loader={blogsLoader} element={<Blogs/>} /> <Route path=":id" element={<Post />} /> </Route>
修改后,/posts/:id会自动继承父路由的posts路径,和旧版本的路由效果一致,同时符合React Router 6的嵌套路由规范。
内容的提问来源于stack exchange,提问作者Huy Phu
相关产品推荐
相关产品推荐

