You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的使用逻辑冲突:

  1. 你已经通过Controller接管了对应name字段的表单控制,此时应该使用Controller提供的field.onChange来同步值,而非直接调用外部传入的setValue;
  2. 直接调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 19:06:32