如何将 useForm 的寄存器与动态参数一起使用?

How can I use useForm's register with dynamic parameter?

我想使用 react-hook-form 创建一个表单,但我遇到了问题。正如我发现的那样,v7 中有一个很大的变化,所以我用作参考的代码不起作用。我尝试修改它,发现问题出在注册上,但我无法动态传递该名称参数。

我的主要组成部分。

import React from 'react';
import i18next from 'i18next';

import { Button, Grid, Typography } from '@material-ui/core';
import { useForm, FormProvider } from 'react-hook-form';
import { Link } from 'react-router-dom';

import FormInput from './CustomTextField'

const AddressForm = ({ next }) => {
    const methods = useForm();

    return (
        <>
            <Typography variant="h6" gutterBottom>
                {i18next.t('shipping_address')}
            </Typography>
            <FormProvider {...methods}>
                <form onSubmit={methods.handleSubmit((data) => {
                    console.log(data);
                    next({ ...data })})}>
                    <Grid container spacing={3}>
                        <FormInput required register={methods.register} name='lastName' label={i18next.t('last_name')} />
                        <FormInput required register={methods.register} name='firstName' label={i18next.t('first_name')} />
                        <FormInput required register={methods.register} name='email' label={i18next.t('mail')} />
                        <FormInput required register={methods.register} name='zip' label={i18next.t('zip_code')} />
                        <FormInput required register={methods.register} name='city' label={i18next.t('city')} />
                        <FormInput required register={methods.register} name='address1' label={i18next.t('address_1')} />
                    </Grid>
                    <br />
                    <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                        <Button component={Link} to="/cart" variant="outlined">
                            {i18next.t('back_to_cart')}
                        </Button>
                        <Button type="submit" variant="contained" color="primary">
                            {i18next.t('next_step')}
                        </Button>
                    </div>
                </form>
            </FormProvider>
        </>
    )
}

export default AddressForm

CustomTextField 组件:

import React from 'react';
import { TextField, Grid } from '@material-ui/core';
import { useFormContext, Controller } from 'react-hook-form';

const CustomTextField = ({ name, label, register, required}) => {
    const { control } = useFormContext();

    return (
        <Grid item xs={12} sm={6}>
            <Controller 
                control={control}
                name={name}
                render = {(field) => (
                    <TextField
                        {...register({name})} // <--- It is not working like this
                        label={label}
                        required={required}
                    />
                )}
            />
        </Grid>
    )
}

export default CustomTextField

根据文档:https://react-hook-form.com/api/useform/register

它将输入字段的名称作为参数,如果我将它作为字符串传入,它就可以正常工作。如何将 name 的值作为参数传递给 register() 函数?

问题是您混合了 RHF 的 <Controller />register。由于 Mui 的 <TextField /> 是一个外部控制组件,您应该使用 <Controller />。查看文档 here 了解更多信息。

const CustomTextField = ({ name, label, register, required}) => {
    const { control } = useFormContext();

    return (
        <Grid item xs={12} sm={6}>
            <Controller 
                control={control}
                name={name}
                render={({ field: { ref, ...field } }) => (
                    <TextField
                        {...field}
                        inputRef={ref}
                        label={label}
                        required={required}
                    />
                )}
            />
        </Grid>
    )
}

如果你真的想在这里使用 register,你必须删除包装 <Controller /> 并将 name 作为字符串传递,而不是像你现在正在做的那样作为对象传递.但我建议使用 <Controller />register 一样,您将失去为 <TextField /> 输入元素设置正确 ref 的功能,因为它是通过 inputRef prop 而不是使用 RHF register 使用的 ref

const CustomTextField = ({ name, label, register, required}) => {
    const { control } = useFormContext();

    return (
        <Grid item xs={12} sm={6}>
            <TextField
                {...register(name)}
                label={label}
                required={required}
            />
        </Grid>
    )
}