如何在React Router动态路由中隔离react-hook-form表单?
解决React动态路由下react-hook-form表单数据共享问题
问题原因:React Router在动态路由参数(如dynamicId)变化时,会复用同一个<DynamicFormPage>组件实例,不会重新挂载。这导致useForm创建的表单状态实例被保留,不同路由下的表单共享了同一状态。
解决方案1:监听路由参数变化,重置表单
通过useEffect监听dynamicId的变化,每次参数切换时调用reset方法清空表单状态:
function DynamicFormPage() { const {dynamicId} = useLoaderData() as {dynamicId: string}; const {register, handleSubmit, reset} = useForm() // 监听dynamicId变化,重置表单 useEffect(() => { reset(); }, [dynamicId, reset]) return ( <> <h2>Dynamic Form Page</h2> <form onSubmit={handleSubmit((data) => { console.log(data); })}> <label> {`Form${dynamicId}-question #1 `} <input type="text" {...register(`${dynamicId}-question1`)} /> </label> <label> {`Form${dynamicId}-question #2 `} <input type="text" {...register(`${dynamicId}-question2`)} /> </label> <label> {`Form${dynamicId}-question #3 `} <input type="text" {...register(`${dynamicId}-question3`)} /> </label> <button type="submit">Submit</button> </form> </> ) }
解决方案2:给组件添加key,强制重新挂载
修改路由配置,给<DynamicFormPage>组件添加基于dynamicId的key,让React在路由参数变化时重新创建组件实例,从而初始化新的表单状态:
const router = createBrowserRouter([ { path: '/', element: ( <> <h1>Router Issue Example</h1> <nav> <NavLink to="forms/1">Pick Form 1</NavLink> <span> | </span> <NavLink to="forms/2">Pick Form 2</NavLink> <span> | </span> <NavLink to="forms/3">Pick Form 3</NavLink> </nav> <Outlet /> </> ), children: [ { path: 'forms/:dynamicId', loader: DynamicFormPageLoader, // 用params的dynamicId作为组件key element: ({ params }) => <DynamicFormPage key={params.dynamicId} /> } ] }, ])
额外优化:统一表单字段命名(可选)
因为每个表单对应唯一的dynamicId,可以简化字段名,不需要在register里加dynamicId前缀,进一步避免字段冲突:
// 表单内的register可以简化为 <input type="text" {...register("question1")} /> <input type="text" {...register("question2")} />
这样每个独立的表单实例都会维护自己的question1、question2字段,不会互相干扰。
内容的提问来源于stack exchange,提问作者Nate Rardin
相关产品推荐
相关产品推荐

