reactjs 如何使用useEffect()更改React-Hook-Form默认值?

xytpbqjk  于 2023-02-04  发布在  React
关注(0)|答案(9)|浏览(362)

我正在为用户创建一个页面,以便使用React-Hook-Form更新个人数据。一旦加载了页面,我将使用useEffect获取用户当前的个人数据,并将其设置为表单的默认值。
我把获取的值放入<Controller />defaultValue中。但是,它没有显示在文本框中。下面是我的代码:

import React, {useState, useEffect, useCallback} from 'react';
import { useForm, Controller } from 'react-hook-form'
import { URL } from '../constants';

const UpdateUserData = props => {
    const [userData, setUserData] = useState(null);
    const { handleSubmit, control} = useForm({mode: 'onBlur'});

    const fetchUserData = useCallback(async account => {
        const userData = await fetch(`${URL}/user/${account}`)
                            .then(res=> res.json());
        console.log(userData);
        setUserData(userData);
    }, []);

    useEffect(() => {
        const account = localStorage.getItem('account');
        fetchUserData(account);
    }, [fetchUserData])

    const onSubmit = async (data) => {
        // TODO
    }

    return (
        <div>
            <form onSubmit={handleSubmit(onSubmit)}>
                <div>
                    <label>User Name:</label>
                    <Controller
                        as={<input type='text' />}
                        control={control}
                        defaultValue={userData ? userData.name : ''}
                        name='name'
                    />
                </div>
                
                <div>
                    <label>Phone:</label>
                    <Controller
                        as={<input type='text' />}
                        control={control}
                        defaultValue={userData ? userData.phone : ''}
                        name='phone'
                    />
                </div>
                <button>Submit</button>
            </form>
        </div>
    );
}

export default UpdateUserData;

调用的API运行良好,值实际上设置为userData状态。

{
  name: "John",
  phone: "02-98541566"
  ...
}

我也尝试过用useEffect()中的mock数据来修改setUserData,但是也不起作用。上面的代码有什么问题吗?

vecaoik1

vecaoik11#

@tam answer已经完成了使它与版本6. 8. 3一起工作所需的一半。
你需要提供默认值,但也要使用Effect来重置。如果你有一个用另一个实体重新加载的表单,那么这个特殊的区别是需要的。我在CodeSanbox here中有一个完整的例子。

**简而言之:**您需要在userForm中定义默认值。

const { register, reset, handleSubmit } = useForm({
    defaultValues: useMemo(() => {
      return props.user;
    }, [props])
  });

然后你需要倾听潜在的变化。

useEffect(() => {
    reset(props.user);
  }, [props.user]);

代码沙盒中的示例允许在两个用户之间进行交换并更改窗体的值。

68bkxrlz

68bkxrlz2#

您可以使用设置值https://react-hook-form.com/api/useform/setvalue)。
从useForm导入:

const { handleSubmit, control, setValue} = useForm({ mode: 'onBlur' });

然后在接收到用户数据后调用它:

useEffect(() => {
    if (userData) {
        setValue([
            { name: userData.name }, 
            { phone: userData.phone }
        ]);
    }
}, [userData]);

您可以从表单中删除默认值。
编辑:如果这不起作用,请参见下面的替代答案。

ybzsozfc

ybzsozfc3#

setValue对我不起作用。或者,您可以使用reset方法:
重置整个窗体状态或部分窗体状态。
下面是工作代码:

/* registered address */
const [registeredAddresses, setRegisteredAddresses] = useState([]);

const { register, errors, handleSubmit, reset } = useForm <FormProps> ({
    validationSchema: LoginSchema,
});

/**
 * get addresses data
 */
const getRegisteredAddresses = async () => {
    try {
        const addresses = await AddressService.getAllAddress();
        setRegisteredAddresses(addresses);
        setDataFetching(false);
    } catch (error) {
        setDataFetching(false);
    }
};

useEffect(() => {
    getRegisteredAddresses();
}, []);

useEffect(() => {
    if (registeredAddresses) {
        reset({
            addressName: registeredAddresses[0].name,
            tel: registeredAddresses[0].contactNumber
        });
    }
}, [registeredAddresses]);
1l5u6lss

1l5u6lss4#

找到了另一种简单的方法,我使用了useForm中的reset API

const { handleSubmit, register, reset } = useForm({ resolver });

调用API并获取响应数据后,使用新的apiData调用reset,确保apiData键与输入键相同(name属性):

useEffect(() => {
    reset(apiData);
  }, [apiData]);

表单的默认值是缓存的,因此一旦从API获得数据,我们就用新数据重置表单状态。

zengzsys

zengzsys5#

@tommcandrew的setValue参数格式对我无效。
此格式:

useEffect(() => {
  const object = localStorage.getItem('object');
  setValue("name", object.name);
}, [])
anauzrmj

anauzrmj6#

虽然这篇文章发表了两个月,但我今天偶然发现了这个问题,并寻找了几种方法来解决这个问题。我想到的最有效的方法是使用useMemo来设置默认值,如下所示:

const { control, errors, handleSubmit } = useForm({
    reValidateMode: 'onChange',
    defaultValues: useMemo(() => yourDefaultValues, [yourDefaultValues]),
});

这使您能够在表单中正确地设置值,如果您碰巧有字段数组(我就是这样做的),则无需进行多次实现。
这也适用于使用官方文档中的高级智能表单组件示例。如果您有任何问题,请告诉我!

hpxqektj

hpxqektj7#

这适用于嵌套对象(我使用的是版本6.15.1)

useEffect(() => {
    for (const [key, value] of Object.entries(data)) {
        setValue(key, value, {
            shouldValidate: true,
            shouldDirty: true
        })
    }
}, [data])
dbf7pr2w

dbf7pr2w8#

使用reset是一个简单的解决方案。

const { reset } = useForm();

onClick={()=> reset({ firstname: 'Joe' }, { lastname: 'Doe' }) }
5anewei6

5anewei69#

从react-hook-form 7.41开始,你可以使用defaultValues和异步函数,如下所示:

const {
  formState: { isLoading },
} = useForm({
  defaultValues: fetch('API'),
  // resetOptions: {
  //   keepDirtyValues: true
  // }
});

现在,defaultValue字段类型如下所示:

type AsyncDefaultValues<TFieldValues> = (payload?: unknown) => Promise<TFieldValues>;
  • isLoading* 表示异步默认值加载状态。

相关问题