React项目中react-router-dom页面刷新报404错误的解决方法
React应用刷新时出现404错误(GET /employees 404)
问题描述
登录后跳转至带导航栏的Root页面,点击导航链接(如/employees)页面正常显示,但刷新浏览器时抛出错误:GET http://localhost:8080/employees 404 (Not Found)。使用react-router-dom的BrowserRouter时出现该问题,换成HashRouter后刷新正常但URL会带#,不符合需求。
相关路由配置代码如下:
index.js
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; ReactDOM.render( <React.StrictMode> <Provider store={store}> <Router> <Routes> <Route path="/*" element={<App />} /> </Routes> </Router> </Provider> </React.StrictMode>, document.getElementById("app") );
App.jsx
function App() { const isLoggedIn = useSelector((state) => state.auth.isLoggedIn); const dispatch = useDispatch(); const navigate = useNavigate(); // 处理登录 const handleLogin = () => { dispatch(login()); }; // 处理登出 const handleLogout = () => { dispatch(logout()); navigate("/", { replace: true }); }; // 刷新页面时校验token有效性 useEffect(() => { const refresh_token = localStorage.getItem("refresh_token"); if (!refresh_token) { navigate("/"); return; } axiosInstance .get("/auth/refresh", { headers: { Authorization: `Bearer ${refresh_token}`, }, }) .then(() => { dispatch(login()); }) .catch((error) => { navigate("/login"); localStorage.clear(); return Promise.reject(error); }); }, [dispatch, navigate]); return ( <Routes> <Route path="/" element={<Login onLogin={handleLogin} />} /> {isLoggedIn ? ( <Route path="/" element={<Root onLogout={handleLogout} />}> <Route index element={<Topics />} /> <Route path="employees" element={<EmployeeList />} /> <Route path="employees/create" element={<RegisterEmployee />} /> <Route path="register" element={<Register />} /> <Route path="dashboard" element={<Dashboard />} /> </Route> ) : null} </Routes> ); } export default App;
原因分析
BrowserRouter依赖HTML5 History API实现无#的URL。点击导航链接时,react-router-dom是在客户端完成路由跳转,不会向服务器发送请求;但刷新页面时,浏览器会直接向服务器请求当前URL(比如/employees),而你的服务器没有配置对应路径的路由,因此返回404。
解决方案
1. 开发环境配置(以Create React App为例)
在项目根目录创建setupProxy.js文件,添加以下代码:
const { createProxyMiddleware } = require('http-proxy-middleware'); const path = require('path'); module.exports = function(app) { // 代理API请求到后端服务器(替换为你的实际API前缀和后端地址) app.use( '/api', createProxyMiddleware({ target: 'http://localhost:3000', changeOrigin: true, }) ); // 所有非API请求都返回index.html,交给客户端路由处理 app.get('*', (req, res) => { res.sendFile(path.resolve(__dirname, 'public', 'index.html')); }); };
2. 生产环境配置
根据服务器类型做对应配置:
- Nginx:在Nginx配置文件中添加
try_files指令,将所有请求指向index.html
server { listen 80; server_name your-domain.com; root /path/to/your/react/app/build; index index.html; location / { try_files $uri $uri/ /index.html; } # 代理API请求到后端 location /api { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
- Express服务器:添加中间件处理所有路由,返回
index.html
const express = require('express'); const path = require('path'); const app = express(); // 托管React构建后的静态文件 app.use(express.static(path.join(__dirname, 'build'))); // 所有路由请求都返回index.html app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'build', 'index.html')); }); app.listen(8080, () => { console.log('Server running on port 8080'); });
3. 代码层面优化
确保axiosInstance配置了正确的baseURL,避免把前端路由误当作API请求:
const axiosInstance = axios.create({ baseURL: '/api', // 替换为你的API前缀 });
内容的提问来源于stack exchange,提问作者raio
相关产品推荐
相关产品推荐

