React hook form 多个表单如何注册到多个表单上下文?

问题描述 投票:0回答:2

我正在尝试使用 React Hook Form 构建一种多步骤表单,但它不是经典的多步骤表单。就我而言,我需要在每次提交时保留在数据库中。

对我来说,这表明我应该将表单拆分为小表单,并单独验证每个表单。

这种方法的唯一问题(但并不简单)是,现在我遇到了一个步骤需要来自另一个步骤的数据的情况。由于每个单独的表单都有自己的

FormProvider
,因此我只能使用
useContext
来访问其对应上下文中的数据。我不想构建另一个上下文只是为了存储所有步骤的所有数据。

这是我目前拥有的结构的插图

interface IForm1 {
    id?: number;
}

interface IForm2 {
    name?: string;
}

const GenericForm = <T extends FieldValues, >(props: PropsWithChildren<T>) => {
    const form = useForm<T>();

    return <FormProvider {...form}>
        <form>
            {props.children}
        </form>
    </FormProvider>;
};

const MyForms = () => <>
    <GenericForm<IForm1>>
        <Component1 />
    </GenericForm>
    <GenericForm<IForm2>>
        <Component1 />
    </GenericForm>
</>;

现在我希望子组件能够从两个上下文访问数据,如下所示:

const Component1 = () => {
    const { watch } = useFormContext<IForm1>();
    const form2Context = useFormContext<IForm2>();

    const id = watch('id');
    const name = form2Context.watch('name');

    return <div>
        {id}
        and
        {name}
    </div>;
};

这是行不通的,因为每个 FormProvider 都处于不同的级别,所以我想到做这样的事情:

const MyForms = () => <>
    <FormProvider {...form1}>
        <FormProvider {...form2}>
            <GenericForm<IForm1>>
                <Component1 />
            </GenericForm>
            <GenericForm<IForm2>>
                <Component1 />
            </GenericForm>
        </FormProvider>
</>;

这也不起作用,最深的 FormProvider 似乎覆盖了所有父母。

有人遇到过这样的问题吗?有什么想法吗?

我正在研究的另一个想法是尝试向父级公开表单方法 -

watch
setValue
并以某种方式将它们注册到记录中。这样任何孩子都可以使用它们。问题是让这些方法保持同步真的很难。

更新

我找到了一种组合 useForm() 实例的方法

It is something like this:

    const form1 = useForm();
    const form2 = useForm();
    
    
    <FormProvider {...{ ...form1, ...form2}}>
       <form>Form 1</form>
       <form>Form 2</form>
    </FormProvider>

问题是,当我尝试使用

useFormContext
时,我可以看到上下文包含一个大对象,其中包含两种形式的所有属性,就好像它们只是简单地组合在一起一样。

我认为上下文会彼此分离,我可以做类似的事情:

const form1 = useFormContext<IForm1>();

这不起作用=/

reactjs react-hooks react-context react-hook-form
2个回答
0
投票

我建议您使用州立图书馆。因为有时当表单开始变得复杂时,使用

React Context
来管理这些表单可能会很痛苦。

我用过的状态管理库是@legendapp/state

它易于使用,并且在大多数情况下都具有高性能。

但是如果你想坚持使用 React 上下文;唯一可能的解决方案是使用一个表单提供程序,每个表单具有不同的对象。

状态对象就像这样:

{
form1: {data},
form2: {data},
form3: {data}
}

然后在每个子表单中,使用

useEffect
useWatch
更新上下文中的数据。


0
投票

@Brian 有一个好主意,这是一个可以动态执行此操作的简单方法

首先你会有这个

<FormProvider {form1, form2}}>
  <Form contextKey="form1">Form 1 </Form>
  <Form contextKey="form1">Form 2 </Form>
</FormProvider>
// and then use your Form
const Form = ({contextKey, children}:{contextKey: string,children: any}) => {
    const form = (useContext() as any)[contextKey];
    // and now based on the contextKey you can get the right form.
    return (
        <form>
            {children}
        </form>
        )
};

您必须使用

state
useEffect
来查看变化。

让我知道你的想法

© www.soinside.com 2019 - 2024. All rights reserved.