Next.js(v14)中react-hook-form多页表单数据跨路由保留求助
多页表单数据持久化解决方案
问题核心是你的FormProvider在路由切换时会重新初始化useForm,且未保留用户已输入的数据,以下是两种可行的解决方法:
方法一:组件内state持久化(仅内存保留,刷新丢失)
修改FormProvider,将表单数据存在组件state中,作为useForm的动态默认值,同时监听表单变化同步更新state:
// FormProvider.tsx import { useState, useEffect } from 'react'; import { useForm, FormProvider as RHFormProvider, Form } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import MyFormSchema from './your-schema-path'; // 替换为你的Schema路径 type MyForm = { name: string; description: string; }; export const FormProvider = ({ children }: { children: React.ReactNode }) => { // 初始化state,默认值为初始空数据 const [formData, setFormData] = useState<MyForm>({ name: '', description: '' }); const form = useForm<MyForm>({ defaultValues: formData, // 动态绑定state作为默认值 resolver: zodResolver(MyFormSchema), }); // 监听表单值变化,实时更新state useEffect(() => { const unsubscribe = form.watch((values) => { setFormData(values); }); return unsubscribe; }, [form]); const onSubmit = (data: MyForm) => { console.log('提交数据:', data); // 提交后可根据需求重置state或执行其他逻辑 }; return ( <RHFormProvider {...form}> <form onSubmit={form.handleSubmit(onSubmit)}> {children} </form> </RHFormProvider> ); };
路由切换时,FormProvider的state会保留之前的输入数据,useForm初始化时会复用该数据,避免重置。
方法二:localStorage持久化(刷新页面也保留)
如果需要刷新页面后仍保留数据,可结合localStorage实现持久化:
// FormProvider.tsx import { useEffect } from 'react'; import { useForm, FormProvider as RHFormProvider, Form } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import MyFormSchema from './your-schema-path'; type MyForm = { name: string; description: string; }; const STORAGE_KEY = 'multi-step-form-data'; export const FormProvider = ({ children }: { children: React.ReactNode }) => { // 从localStorage读取已有数据,无数据则用默认值 const getDefaultValues = (): MyForm => { const saved = localStorage.getItem(STORAGE_KEY); return saved ? JSON.parse(saved) : { name: '', description: '' }; }; const form = useForm<MyForm>({ defaultValues: getDefaultValues(), resolver: zodResolver(MyFormSchema), }); // 监听表单变化,实时保存到localStorage useEffect(() => { const unsubscribe = form.watch((values) => { localStorage.setItem(STORAGE_KEY, JSON.stringify(values)); }); return unsubscribe; }, [form]); const onSubmit = (data: MyForm) => { console.log('提交数据:', data); // 提交完成后可清除localStorage中的缓存 localStorage.removeItem(STORAGE_KEY); }; return ( <RHFormProvider {...form}> <form onSubmit={form.handleSubmit(onSubmit)}> {children} </form> </RHFormProvider> ); };
注意:若表单包含敏感数据,建议改用sessionStorage或方法一的内存state,避免数据泄露。
另外,如果你使用Next.js 14的App Router,需将FormProvider放在layout.tsx中(Pages Router则保持_app.tsx的写法即可),确保路由切换时FormProvider不会被卸载。
内容的提问来源于stack exchange,提问作者kayu
相关产品推荐
相关产品推荐

