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

如何在React Final Form的Field组件中传递Props给内部组件

解决react-final-form中Field组件向自定义组件传递props的问题

我用react-final-form做了个表单,里面有个管理图片上传的Field,用的是函数组件UploadImage。之前把这个组件放在父组件里,SonarLint警告不符合最佳实践,移到外部后发现必须传props才能正常工作,但不知道怎么在Field里传props,求解决。

现有代码

表单中的Field代码

<div className="col-md-1 mb-4">
  <label htmlFor="image" className="form-label text-center" >
    <h5> Imagen </h5>
  </label>
</div>
<div className="col-md-5">
  <Field
    name="image"
    type="file"
    component={UploadImage} // 需要传props的组件
    onKeyDown={(e) => { e.key === 'Enter' && e.preventDefault(); }}
  />
</div>

外部的UploadImage组件

function UploadImage({setImageUpdate, image, imageUpdate}) {
  const onDrop = useCallback((file) => { 
    console.log('file', file);     
    /*  input.onChange(file);
        console.log(input.onChange(file)); */
    getImages()
      .then(imagesFolder => {          
        if (imagesFolder.includes(file[0].name)) {
          confirm({
            title: "Reemplazar Imagen",
            content: `La imagen ${file[0].name} ya existe en la base de datos. Quieres cambiarla igualmente?`,
            okText: "Sustituir",
            okType: "danger",
            cancelText: "Cancelar",
            onOk() {
              setImageUpdate(file);
            }
          });
        } else {
          setImageUpdate(file);
        }
      })
      .catch(error => console.log(error));
  }, []);

  const { getRootProps, getInputProps } = useDropzone({
    accept: "image/jpeg",
    noKeyboard: true,
    onDrop,
  });

  function handleRemoveClick (imageUpdate){     
    confirm({
      title: "Borrar Imagen",
      content: `Seguro que quieres eliminar la imagen ${imageUpdate}?`,
      okText: "Borrar",
      okType: "danger",
      cancelText: "Cancelar",
      onOk() {         
        setImageUpdate([]);
      }
    });
  }

  return (
    <div>
      {imageUpdate.length === 0 || imageUpdate[0] === "" ? (
        <div {...getRootProps()}>
          <input {...getInputProps()} />
          <div className="btn btn-outline-primary" >Click or Drag to Upload</div>
        </div>
      ) : (
        <>
          {imageUpdate[0].name || image} <div className="btn btn-outline-danger ms-4" onClick={() => handleRemoveClick(image)}><i className="bi bi-trash"></i> </div>
        </>
      )}
    </div>
  );
}

解决方案

react-final-form的Field组件支持直接传递自定义props,这些props会和Field内部的input、meta等参数一起传递给自定义组件。另外,你还需要注意组件要接收react-final-form传入的input对象,用来更新表单字段的值。

方法1:直接在Field上传递props

只需要在Field组件上添加需要传递的props,比如setImageUpdate、image、imageUpdate,这些props会自动传递给UploadImage组件:

<div className="col-md-5">
  <Field
    name="image"
    type="file"
    component={UploadImage}
    onKeyDown={(e) => { e.key === 'Enter' && e.preventDefault(); }}
    // 直接添加需要传递的props
    setImageUpdate={setImageUpdate}
    image={image}
    imageUpdate={imageUpdate}
  />
</div>

然后修改UploadImage组件,同时接收react-final-form的input参数(用来更新表单值):

// 新增input参数,同时保留自定义props
function UploadImage({ input, setImageUpdate, image, imageUpdate }) {
  const onDrop = useCallback((file) => { 
    console.log('file', file);     
    // 更新react-final-form的表单字段值
    input.onChange(file);
    getImages()
      .then(imagesFolder => {          
        if (imagesFolder.includes(file[0].name)) {
          confirm({
            title: "Reemplazar Imagen",
            content: `La imagen ${file[0].name} ya existe en la base de datos. Quieres cambiarla igualmente?`,
            okText: "Sustituir",
            okType: "danger",
            cancelText: "Cancelar",
            onOk() {
              setImageUpdate(file);
            }
          });
        } else {
          setImageUpdate(file);
        }
      })
      .catch(error => console.log(error));
  }, [input, setImageUpdate]); // 依赖项添加input和setImageUpdate

  const { getRootProps, getInputProps } = useDropzone({
    accept: "image/jpeg",
    noKeyboard: true,
    onDrop,
  });

  function handleRemoveClick (){     
    confirm({
      title: "Borrar Imagen",
      content: `Seguro que quieres eliminar la imagen ${imageUpdate[0]?.name || image}?`,
      okText: "Borrar",
      okType: "danger",
      cancelText: "Cancelar",
      onOk() {         
        setImageUpdate([]);
        // 清空表单字段值
        input.onChange([]);
      }
    });
  }

  return (
    <div>
      {imageUpdate.length === 0 || imageUpdate[0] === "" ? (
        <div {...getRootProps()}>
          <input {...getInputProps()} />
          <div className="btn btn-outline-primary" >Click or Drag to Upload</div>
        </div>
      ) : (
        <>
          {imageUpdate[0].name || image} 
          <div className="btn btn-outline-danger ms-4" onClick={handleRemoveClick}>
            <i className="bi bi-trash"></i> 
          </div>
        </>
      )}
    </div>
  );
}

方法2:使用render prop方式(更灵活)

如果需要更灵活的控制,也可以用Field的render prop模式,手动传递props:

<div className="col-md-5">
  <Field
    name="image"
    type="file"
    onKeyDown={(e) => { e.key === 'Enter' && e.preventDefault(); }}
  >
    {(input) => (
      <UploadImage
        input={input}
        setImageUpdate={setImageUpdate}
        image={image}
        imageUpdate={imageUpdate}
      />
    )}
  </Field>
</div>

这种方式下,UploadImage组件的写法和方法1中修改后的组件一致,同样需要接收input和自定义props。

额外注意点

  • 确保useCallback的依赖项正确,避免闭包问题;
  • 删除图片时记得同时调用input.onChange([])清空表单字段的值;
  • 这样修改后,UploadImage组件可以作为通用工具组件在多个表单中复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 12:05:42