React Router v6.9.0+React Hook Form表单提交后重定向报错解决
解决React Router v6中表单提交后重定向的Hook调用问题
问题原因
你遇到的错误源于React Hook的调用规则:Hook只能在React函数组件或自定义Hook的顶层作用域中调用,而你的onSubmit是普通函数,不符合规则,因此无法直接在其中使用useNavigate。
解决方案
把useNavigate的调用移到TheForm组件内部,再将导航能力传递给提交逻辑,以下是两种可行的实现方式:
方式一:将提交逻辑定义在组件内部
直接把onSubmit函数放在组件内部,这样就能直接访问组件内的navigate方法:
import React from 'react'; import { useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; function TheForm() { // 在组件顶层调用useNavigate Hook const navigate = useNavigate(); const { register, handleSubmit, watch, formState: { errors }, } = useForm(); // 提交逻辑定义在组件内部 const onSubmit = (data) => { alert(JSON.stringify(data, null, 4)); fetch("/api/submitHo", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }).then(response => response.json()) .then(res => { console.log(res); // 直接调用navigate完成重定向 navigate("/"); }) .catch(err => { console.error("提交失败:", err); // 可选:添加错误处理逻辑 }); } return ( <React.Fragment> <form onSubmit={handleSubmit(onSubmit)}> {/* 表单内容 */} </form> </React.Fragment> ); } export default TheForm
方式二:将navigate作为参数传递给外部提交函数
如果希望onSubmit保持独立,可以把组件内的navigate作为参数传入:
import React from 'react'; import { useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; // 外部提交函数接收data和navigate两个参数 function onSubmit(data, navigate){ alert(JSON.stringify(data, null, 4)); fetch("/api/submitHo", { method: "POST", headers: { "Content-Type": "application/json" }, body:JSON.stringify(data) }).then(response => response.json()) .then(res => { console.log(res); navigate("/"); }) .catch(err => { console.error("提交失败:", err); }); } function TheForm() { const navigate = useNavigate(); const { register, handleSubmit, watch, formState: { errors }, } = useForm(); return ( <React.Fragment> {/* 调用handleSubmit时,把navigate传递给onSubmit */} <form onSubmit={handleSubmit((data) => onSubmit(data, navigate))}> {/* 表单内容 */} </form> </React.Fragment> ); } export default TheForm
关键规则提醒
- 所有React Hook(如
useNavigate、useForm)必须在函数组件的顶层调用,不能嵌套在普通函数、条件判断或循环中。 - 你的路由配置从现有代码看是正确的,
"/"路径对应的Root组件包含Outlet,重定向后能正常渲染对应内容。
内容的提问来源于stack exchange,提问作者a9z0
相关产品推荐
相关产品推荐

