嗨,我是 Nextjs(v14) 的新手。我想使用react-hook-form 实现多页面表单。 不过,好像每次都会执行
useForm
,并且在页面路由时设置defaultValues
(点击<Link to=XX>
)。
如何跨多个页面保存表单数据?
请帮助我。
这是我的代码。
_app.tsx
return (
<div>
<FormProvider>
<Component {...pageProps} />
</FormProvider>
</div>
);
FormProvider.tsx
export const FormProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const defaultValues: MyForm = {
name: '',
description: ''
};
const form = useForm({
defaultValues,
resolver: zodResolver(MyFormSchema),
});
const onSubmit = () => console.log("something to do");
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>{children}</form>
</Form>
);
};
您正在寻找的是跨多个页面维护的某种全局状态。对于这个例子,我将使用 React 的上下文 API,如果这不适合您的用例,您可以找到一些其他状态管理库。
首先,您需要创建一个全局上下文,并在表单提供程序中包含一个全局状态
// FormProvider.tsx
import { createContext, useContext, useState } from 'react';
const FormContext = createContext();
// Exported to be used in other components
export const useFormContext = () => useContext(FormContext);
export const FormProvider = ({ children }) => {
const [formData, setFormData] = useState({});
return (
<FormContext.Provider value={{ formData, setFormData }}>
{children}
</FormContext.Provider>
);
};
现在您需要用
FormProvider
包装您的应用程序
// You are already doing this part
//_app.tsx
return (
<div>
<FormProvider>
<Component {...pageProps} />
</FormProvider>
</div>
)
现在你可以像这样使用它了。请记住,您将更新表单的全局状态,该状态将在您的所有页面上发生变化。
// In your form component
import { useForm } from 'react-hook-form';
import { useFormContext } from '../path/to/formContext';
const MyFormComponent = () => {
const { formData, setFormData } = useFormContext();
const { register, handleSubmit } = useForm({
defaultValues: formData,
resolver: zodResolver(MyFormSchema),
});
const onSubmit = (data) => {
setFormData(data);
// Handle form submission
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* Form fields */}
</form>
);
};
您可以从其他页面访问数据的示例
// In another page or component
import { useFormContext } from '../path/to/formContext';
const AnotherPage = () => {
const { formData } = useFormContext();
// Use formData as needed
};