React Router errorElement未渲染:组件抛错不触发错误路由
问题原因与解决办法
原因
React Router的errorElement只能捕获组件同步渲染阶段的异常,以及loader/action中的异常。而你在useEffect内部异步函数里抛错,属于异步执行阶段的错误,不在React Router的错误捕获范围内,所以触发不了errorElement。
解决方案
方案1:把异步逻辑移到loader中
将获取用户信息的逻辑迁移到路由的loader函数,这样抛出的错误会被React Router捕获并触发errorElement:
// 路由配置示例 createBrowserRouter([ { path: "/", element: <RootLayout />, errorElement: <ErrorPage />, loader: async () => { try { const res = await axios.get("http://localhost:5000/api/v1/users/showMe", { withCredentials: true, }); return res.data.user; } catch (err) { if (err.response?.status === 401) { return null; } throw json({ message: err.message }, { status: 500 }); } } } ]); // RootLayout中获取loader数据 const RootLayout = () => { const user = useLoaderData(); const [userName, setUserName] = useState(user?.name); const [userId, setUserId] = useState(user?.userId); // 其余代码保持不变 };
方案2:使用React错误边界捕获异步错误
如果必须保留useEffect里的逻辑,可以借助错误边界处理异步错误。推荐使用react-error-boundary库的useErrorBoundary钩子:
import { useErrorBoundary } from 'react-error-boundary'; const RootLayout = () => { const { showBoundary } = useErrorBoundary(); const location = useLocation(); const [userName, setUserName] = useState(); const [userId, setUserId] = useState(); useEffect(() => { const showMe = async () => { try { const res = await axios.get("http://localhost:5000/api/v1/users/showMe", { withCredentials: true, }); if (res.data.user) { setUserName(res.data.user.name); setUserId(res.data.user.userId); } } catch (err) { if (err.response?.status === 401) { setUserName(null); setUserId(null); } if (err.message) { // 手动触发错误边界 showBoundary(new Error(err.message)); } } }; showMe(); }, [location, showBoundary]); // 其余代码保持不变 }; // 路由配置中用ErrorBoundary包裹RootLayout(或直接在路由外包裹) createBrowserRouter([ { path: "/", element: ( <ErrorBoundary fallback={<ErrorPage />}> <RootLayout /> </ErrorBoundary> ), errorElement: <ErrorPage /> } ]);
内容的提问来源于stack exchange,提问作者Shaharin Ahmed
相关产品推荐
相关产品推荐

