React严格模式下HTTP 403状态的正确重定向方案咨询
解决Strict Mode下403重定向两次的问题
核心思路
Strict Mode在开发环境会重复触发组件挂载/渲染,目的是检测非幂等操作。要解决重定向两次的问题,关键是让导航逻辑幂等(执行多次和执行一次效果一致),同时避免重复触发导航动作。
方案1:利用TanStack Query的错误捕获(更推荐)
HTTP 403属于请求错误,应该通过useSuspenseQuery的错误处理逻辑精准捕获,而非依赖data是否为null判断。结合React Router的导航特性确保幂等:
import { useSuspenseQuery } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; import { useEffect } from 'react'; const YourComponent = () => { const navigate = useNavigate(); const { error } = useSuspenseQuery({ queryKey: ['your-data-key'], queryFn: async () => { const res = await fetch('/api/your-endpoint'); if (!res.ok) { const err = new Error('请求失败'); // 将HTTP状态码挂载到错误对象上 err.status = res.status; throw err; } return res.json(); }, }); useEffect(() => { if (error?.status === 403) { // 先判断当前路径,避免重复导航 if (window.location.pathname !== '/sign-in') { navigate('/sign-in', { replace: true }); // replace替换当前历史记录,避免栈混乱 } } }, [error, navigate]); // 正常渲染逻辑 return <div>页面内容</div>; };
方案2:优化条件渲染的重定向逻辑
如果坚持通过data是否为null判断,可使用useRef标记是否已执行过重定向,确保动作只触发一次:
import { useSuspenseQuery } from '@tanstack/react-query'; import { Navigate } from 'react-router-dom'; import { useRef, useEffect } from 'react'; const YourComponent = () => { const hasRedirected = useRef(false); const { data } = useSuspenseQuery(...); useEffect(() => { if (data == null && !hasRedirected.current) { hasRedirected.current = true; } }, [data]); if (data == null && hasRedirected.current) { return <Navigate to='/sign-in' replace />; } // 正常渲染逻辑 return <div>页面内容</div>; };
关键注意点
- 用
replace: true导航:替换当前历史条目,避免用户返回无权限页面,同时减少重复导航导致的历史栈混乱。 - 保证幂等性:无论是错误捕获还是标记位方案,都要确保导航动作仅执行一次,不受Strict Mode重复渲染影响。
- 优先捕获HTTP错误:403属于请求失败,在
queryFn中抛出带状态码的错误,比依赖data为null的判断逻辑更精准,能区分其他导致data为空的场景。
内容的提问来源于stack exchange,提问作者Morse
相关产品推荐
相关产品推荐

