如何在子请求函数而非父组件中调用navigate("*")实现跳转?
问题根源
useNavigate 是React Router的Hook,必须严格遵循Hook规则:只能在React函数组件的顶层或者自定义Hook函数(命名以use开头)的顶层调用。你的redirectGetRequest是普通异步函数,哪怕改名叫useRedirectGetRequest,因为内部包含await这类异步操作破坏了Hook顶层调用的要求,所以依然报错。
方案一:将navigate作为参数传入请求函数
直接从父组件把navigate实例传递给请求函数,既避开Hook调用限制,又能统一在请求函数里处理跳转逻辑。
修改请求函数:
export const redirectGetRequest = async (endpoint, navigate) => { var result = "" var errorMsg = {}; try { const get_response = await Axios.get(`${window.ipAddress.ip}/${endpoint}`); if (get_response.data !== null && get_response.status === 200) { result = get_response.data; } else { // 处理成功响应但数据异常的情况 } } catch (err) { if (err.response?.status === 404) { navigate('*') } else { errorMsg = 'alternative error' } console.log("error", err) } return result; }
父组件中传入navigate:
import { useNavigate } from 'react-router-dom'; // 组件内部 const navigate = useNavigate(); useEffect(() => { fetchData() }, []) async function fetchData() { var data = await redirectGetRequest(`Quizzes/${quizId}`, navigate) setQuiz(data) }
方案二:封装成自定义Hook(更符合React规范)
把请求逻辑封装成自定义Hook,这样就能合法使用useNavigate,同时将错误跳转逻辑彻底统一在Hook内部,组件只需调用Hook获取数据即可。
创建自定义Hook:
import { useNavigate } from 'react-router-dom'; import Axios from 'axios'; export const useRedirectGetRequest = () => { const navigate = useNavigate(); const fetchData = async (endpoint) => { var result = "" var errorMsg = {}; try { const get_response = await Axios.get(`${window.ipAddress.ip}/${endpoint}`); if (get_response.data !== null && get_response.status === 200) { result = get_response.data; } else { // 处理成功响应但数据异常的情况 } } catch (err) { if (err.response?.status === 404) { navigate('*') } else { errorMsg = 'alternative error' } console.log("error", err) } return result; } return fetchData; }
父组件中使用Hook:
import { useRedirectGetRequest } from './path-to-your-hook'; // 组件内部 const redirectGetRequest = useRedirectGetRequest(); useEffect(() => { fetchData() }, []) async function fetchData() { var data = await redirectGetRequest(`Quizzes/${quizId}`) setQuiz(data) }
补充说明
方案一适合快速修改现有代码,改动量小;方案二更贴合React的Hook设计思路,逻辑封装更彻底,后续维护更便捷。两种方案都能满足你“统一在请求函数中处理错误跳转”的需求,无需在每个父组件中重复编写跳转逻辑。
内容的提问来源于stack exchange,提问作者ABpositive
相关产品推荐
相关产品推荐

