如何在react-hook-form中为Datepicker动态设置异步来源的defaultValue
问题原因
react-hook-form的
defaultValue/defaultValues确实只会在首次渲染时缓存,你的组件首次渲染时API还未返回product数据,所以拿到的是初始值null,后续product更新也不会自动同步到表单默认值。
解决方法
优先选择方案2,能从根源避免异步数据和表单渲染的时序问题,代码维护成本最低。
方案1:使用reset方法同步异步数据
在useEffect中监听product的变化,拿到完整数据后调用reset方法更新整个表单的默认值:
const ProductEdit = (props) => { const { product } = props; const { control, register, handleSubmit, formState: { errors }, reset } = useForm(); useEffect(() => { // 当product加载完成后重置表单值 if (product) { reset({ dateLaunch: product.dateLaunch, // 其他表单字段的默认值也可以在这里统一设置 }) } }, [product, reset]) return ( <Controller control={control} name='dateLaunch' render={({ field }) => ( <DatePicker selected={field.value} onChange={(date) => field.onChange(date)} /> )} /> ) }
方案2:条件渲染表单组件
在父组件中判断product是否加载完成,加载完成后再渲染ProductEdit组件,保证表单首次渲染时就能拿到完整的默认值:
// 父组件示例代码 { product && <ProductEdit product={product} /> }
这种方案下不需要额外处理表单的默认值同步,首次渲染useForm时就可以直接传入正确的defaultValues:
const { control, register, handleSubmit, formState: { errors } } = useForm({ defaultValues: { dateLaunch: props.product.dateLaunch } });
方案3:单个字段单独同步
如果只需要处理单个DatePicker字段,也可以用setValue单独更新该字段的值:
const ProductEdit = (props) => { const { product } = props; const { control, register, handleSubmit, formState: { errors }, setValue } = useForm(); useEffect(() => { if (product?.dateLaunch) { setValue('dateLaunch', product.dateLaunch) } }, [product, setValue]) return ( <Controller control={control} name='dateLaunch' render={({ field }) => ( <DatePicker selected={field.value ?? null} // 兜底处理空值避免DatePicker报错 onChange={(date) => field.onChange(date)} /> )} /> ) }
内容的提问来源于stack exchange,提问作者tickwave
相关产品推荐
相关产品推荐

