react-hook-form搭配react-dropzone时setValue失效的解决方案咨询
React Hook Form + React Dropzone:使用props传递的name调用setValue不生效的解决方法
问题描述
在结合React Hook Form的Controller组件与React Dropzone使用时,遇到以下异常:
- 在
onDrop回调中调用setValue,若第一个参数是直接写死的字符串,表单值能正常更新; - 但如果第一个参数是从props接收的name属性(例如
aaaaa),表单参数完全不更新,值无法被注册。
问题原因
核心问题在于Controller的使用逻辑冲突:
- 你已经通过
Controller接管了对应name字段的表单控制,此时应该使用Controller提供的field.onChange来同步值,而非直接调用外部传入的setValue; - 直接调用
props.setValue会绕过Controller内部的状态同步机制,甚至可能因字段路径上下文问题(比如嵌套字段场景),导致表单状态无法正确更新。
解决方案
直接使用Controller渲染回调中提供的field.onChange处理文件选择后的更新逻辑,同时让Dropzone的文件列表与表单字段值保持同步:
export default function FileUpload(props: Props) { return ( <Controller control={props.control} name={props.name} render={({ field: { onChange, onBlur, value } }) => ( <Dropzone noClick onDrop={(acceptedFiles) => { // 改用Controller提供的onChange更新表单值,替代props.setValue onChange(acceptedFiles[0]); }} // 让Dropzone初始文件列表与表单当前值同步 initialFiles={value ? [value] : []} > {({ getRootProps, getInputProps, open, isDragActive, acceptedFiles, }) => ( <div> <div style={{ borderStyle: 'dashed', backgroundColor: isDragActive ? `#808080` : 'transparent', }} {...getRootProps()} > <Input type="hidden" {...getInputProps({ onBlur, onChange, })} /> <Stack className={"mx-1 mt-1"}> <PrimaryButton type={"button"} onClick={open}> ファイルを選択 </PrimaryButton> <Typography fontSize={15}>またはドラッグ&ドロップ</Typography> <Typography fontSize={15}> {acceptedFiles.length !== 0 && acceptedFiles[0].name} </Typography> </Stack> </div> {props.errors && props.name in props.errors && ( <Typography className={"mt-1.5 ml-3 text-xs"} color={'#d32f2f'}> {props.errors[props.name]?.message} </Typography> )} </div> )} </Dropzone> )} /> ); }
额外说明
- 添加
initialFiles={value ? [value] : []}是为了让Dropzone的文件列表与表单字段的当前值保持同步,比如表单初始化时有已上传的文件,Dropzone能正确显示; Controller的field.onChange已经内置了与React Hook Form表单状态同步的逻辑,无需手动调用setValue,能避免字段路径、状态同步等潜在问题。
内容的提问来源于stack exchange,提问作者hiroyukiii
相关产品推荐
相关产品推荐

