React Router:动态路由参数无效时如何返回404页面?
解决React Router中无效pageId导致应用崩溃并跳转到404页面的方案
嘿,这个问题我之前做项目的时候也碰到过,其实可以通过几种方式来处理,既避免应用崩溃,又能优雅地跳转到404页面,具体看你用的React Router版本:
方式一:在Template组件内处理API响应并手动重定向
这是最通用的方案,不管是React Router v5还是v6都适用,核心思路是在请求API后判断返回结果,如果页面不存在,就触发重定向。
如果使用React Router v5
用useHistory钩子来实现跳转:
import { useHistory, useParams } from 'react-router-dom'; import { useState, useEffect } from 'react'; function Template() { const { pageId } = useParams(); const history = useHistory(); const [pageContent, setPageContent] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchPage = async () => { try { const res = await fetch(`/your-api-url/${pageId}`); // 先判断请求是否成功(比如API返回404状态码) if (!res.ok) { throw new Error('Requested page does not exist'); } const content = await res.json(); setPageContent(content); } catch (err) { // 捕获到错误后,重定向到404页面 history.push('/404'); } finally { setIsLoading(false); } }; fetchPage(); }, [pageId, history]); if (isLoading) { return <div>Loading page content...</div>; } return <div>{pageContent?.content}</div>; }
如果使用React Router v6
v6里把useHistory换成了useNavigate钩子:
import { useNavigate, useParams } from 'react-router-dom'; import { useState, useEffect } from 'react'; function Template() { const { pageId } = useParams(); const navigate = useNavigate(); const [pageContent, setPageContent] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchPage = async () => { try { const res = await fetch(`/your-api-url/${pageId}`); if (!res.ok) { throw new Error('Requested page does not exist'); } const content = await res.json(); setPageContent(content); } catch (err) { // 重定向到404页面 navigate('/404'); } finally { setIsLoading(false); } }; fetchPage(); }, [pageId, navigate]); if (isLoading) { return <div>Loading page content...</div>; } return <div>{pageContent?.content}</div>; }
方式二:用React Router v6的errorElement实现优雅错误捕获
如果你的项目用的是React Router v6.4+,可以用官方提供的errorElement来统一处理路由级别的错误,这种方式更简洁:
- 首先定义一个404/错误页面组件:
import { useRouteError, Link } from 'react-router-dom'; function ErrorPage() { const error = useRouteError(); console.error('Page error:', error); return ( <div className="error-page"> <h1>Oops! Page Not Found</h1> <p>Sorry, the page you're looking for doesn't exist.</p> <Link to="/">Go back to homepage</Link> </div> ); }
- 然后在路由配置里给
/:pageId路由加上errorElement:
import { Routes, Route } from 'react-router-dom'; import Template from './Template'; import ErrorPage from './ErrorPage'; function AppRoutes() { return ( <Routes> <Route path="/:pageId" element={<Template />} errorElement={<ErrorPage />} /> {/* 也可以单独配置404路由,处理其他无效路径 */} <Route path="*" element={<ErrorPage />} /> </Routes> ); }
- 最后在Template组件里,当API请求失败时直接抛出错误,
errorElement会自动捕获并渲染错误页面:
import { useParams } from 'react-router-dom'; import { useState, useEffect } from 'react'; function Template() { const { pageId } = useParams(); const [pageContent, setPageContent] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchPage = async () => { try { const res = await fetch(`/your-api-url/${pageId}`); if (!res.ok) { throw new Error('Page not found'); } const content = await res.json(); setPageContent(content); } catch (err) { // 抛出错误,让errorElement捕获 throw err; } finally { setIsLoading(false); } }; fetchPage(); }, [pageId]); if (isLoading) { return <div>Loading page content...</div>; } return <div>{pageContent?.content}</div>; }
额外注意点
- 不管用哪种方式,都要确保你的路由配置里已经有对应的404页面路由(比如
/404或者path="*")。 - 处理API请求时,不仅要判断
response.ok(覆盖HTTP错误状态码),还要捕获网络请求失败的情况(比如断网),这些情况都会进入catch块,从而触发重定向。
内容的提问来源于stack exchange,提问作者ahols
相关产品推荐
相关产品推荐

