React Router DOM中Form组件useSubmit报错排查求助
解决React Router Form组件报错:useSubmit must be used within a data router
错误原因
你的<Cart>组件(包含报错的Checkout)是和<RouterProvider>同级渲染的,完全处于React Router的路由上下文之外。React Router提供的<Form>组件内部会自动调用useSubmit钩子,而这个钩子必须在createBrowserRouter创建的数据路由上下文(即RouterProvider的子组件树)中才能正常工作。其他页面的Form能正常使用,是因为它们都嵌套在路由的children节点里,属于RouterProvider的上下文范围。
解决方法
方案一:将弹窗组件移入路由上下文
把<Cart>和<UserMenu>移到路由根组件(RootLayout)内部,这样它们就会处于React Router的上下文环境中:
- 修改
App.js的返回内容,只保留RouterProvider:
function App() { const { isLoggedIn } = useAuth(); const cartIsShown = useSelector((state) => state.modalState.cartIsShown); const userMenuIsShown = useSelector( (state) => state.modalState.userMenuIsShown ); const router = createBrowserRouter([/* 原有路由配置 */]); return <RouterProvider router={router} />; }
- 在
RootLayout.js中添加弹窗组件的渲染逻辑:
import { Fragment } from "react"; import { Outlet } from "react-router-dom"; import { useSelector } from "react-redux"; import Cart from "./Cart/Cart"; import UserMenu from "./UserMenu"; import useAuth from "../Utility/use-auth"; const RootLayout = () => { const { isLoggedIn } = useAuth(); const cartIsShown = useSelector((state) => state.modalState.cartIsShown); const userMenuIsShown = useSelector((state) => state.modalState.userMenuIsShown); return ( <Fragment> {cartIsShown && <Cart />} {userMenuIsShown && isLoggedIn && <UserMenu />} <Outlet /> </Fragment> ); }; export default RootLayout;
这样修改后,Checkout中的<Form>组件就能正常访问路由上下文,useSubmit钩子也不会再报错。
方案二:改用原生form元素
如果不想调整组件结构,可以直接把Checkout中的<Form>替换为原生HTML的<form>标签,保持原有提交逻辑不变:
// Checkout.js中修改return部分 return ( <form className={classes.form} onSubmit={confirmHandler}> {/* 原有表单内容不变 */} </form> );
这种方式绕过React Router的Form组件,完全自定义提交逻辑,适合不需要利用路由action的场景。
内容的提问来源于stack exchange,提问作者Priyansh
相关产品推荐
相关产品推荐

