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

如何在JavaScript中结合React Hook Form使用Mantine Dropzone?

React Hook Form 结合 Mantine Dropzone 实现文件上传模态框

要在React Hook Form中使用Mantine Dropzone,核心是用Controller组件桥接自定义组件(Dropzone)和表单——因为Dropzone不是原生file输入框,无法直接通过register绑定。以下是完整的实现方案:

完整代码实现

import { useForm, Controller } from 'react-hook-form';
import { Button, Text, Box } from '@mantine/core';
import { Dropzone, IMAGE_MIME_TYPE } from '@mantine/dropzone';

export default function UploadForm({ isVisible, onClose }) {
  const { control, handleSubmit, formState: { errors } } = useForm({
    defaultValues: {
      file: null // 设置文件字段默认值为空
    }
  });

  const onSubmit = (data) => {
    console.log('待上传文件:', data.file);
    // 此处可添加文件上传逻辑,比如调用后端API
    onClose(); // 提交完成后关闭模态框
  };

  if (!isVisible) return null;

  return (
    <Box className="bg-white shadow sm:rounded-lg p-6">
      <h3 className="text-lg leading-6 font-medium text-gray-900 mb-4">上传文件</h3>
      <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
        {/* 用Controller包裹Dropzone,实现表单绑定 */}
        <Controller
          name="file"
          control={control}
          rules={{ required: '请选择一个文件上传' }}
          render={({ field }) => (
            <Dropzone
              accept={IMAGE_MIME_TYPE} // 仅接受图片类型,可按需修改为其他MIME类型
              maxSize={3 * 1024 * 1024} // 限制文件大小为3MB
              onDrop={(files) => field.onChange(files[0])} // 单文件上传取第一个,多文件直接传files数组
              onReject={(rejectedFiles) => console.log('不符合要求的文件:', rejectedFiles)}
            >
              {({ getRootProps, getInputProps, acceptedFiles, rejectedFiles }) => (
                <div
                  {...getRootProps()}
                  className={`border-2 border-dashed rounded-lg p-8 text-center ${
                    acceptedFiles.length > 0 ? 'border-green-500' : 'border-gray-300'
                  }`}
                >
                  <input {...getInputProps()} />
                  {acceptedFiles.length === 0 ? (
                    <Text>拖拽文件到这里,或点击选择文件</Text>
                  ) : (
                    <Text className="text-green-600">已选择: {acceptedFiles[0].name}</Text>
                  )}
                  {rejectedFiles.length > 0 && (
                    <Text className="text-red-600 mt-2">文件类型或大小不符合要求</Text>
                  )}
                </div>
              )}
            </Dropzone>
          )}
        />

        {/* 展示表单验证错误 */}
        {errors.file && (
          <Text className="text-red-600 text-sm">{errors.file.message}</Text>
        )}

        {/* 提交按钮 */}
        <div className="flex justify-end">
          <Button
            type="submit"
            className="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md"
          >
            上传文件
          </Button>
        </div>
      </form>
    </Box>
  );
}

关键要点说明

  • Controller组件的作用:作为React Hook Form和自定义组件的中间层,负责传递表单状态和更新方法,解决原生register无法绑定非标准输入组件的问题。
  • Dropzone事件处理:通过onDrop将选中的文件传递给表单字段,单文件场景取数组第一个元素,多文件场景直接传递数组即可。
  • 双层验证机制:既可以通过Dropzone的accept、maxSize做前端前置验证,也可以通过Controller的rules配置表单级验证,同时展示错误提示。
  • 模态框逻辑保留:延续原有isVisible控制组件显示,提交后触发onClose关闭模态框。

内容的提问来源于stack exchange,提问作者Fuviathan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:35:14