如何在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
相关产品推荐
相关产品推荐

