如何用Formik的useFormik钩子实现文件上传、预读内容并提交到接口
核心问题解答
1. FormData 和 FileReader 怎么选?
- 如果你只需要把文件原封不动传给后端,后端接受
multipart/form-data格式:直接用new FormData()把选中的File对象塞进去就行,不需要读内容。 - 如果你需要提交前预览内容、前端校验JSON格式、修改内容再提交:必须用
FileReader读取文件文本内容,刚好匹配你当前的需求场景。
2. 提交前需要先读取文件内容吗?
你要预览打印内容,就必须提前读。如果不需要预览,只是纯上传文件,就不用读。
代码修改方案
你当前的核心问题是:FileReader.onload是异步回调,你在回调里return的result无法被外部获取,也没有存到Formik的状态里,所以onSubmit里取不到文件内容。
修改后代码如下:
import { useFormik } from 'formik'; import axios from 'axios'; export const MyUploadPerfectAssetForm = () => { const formik = useFormik({ initialValues: { name: null, tags: null, type: null, s3URL: null, thumbnailImageURL: null, // 新增字段存读取到的JSON内容和原始文件 jsonContent: null, rawFile: null }, onSubmit: async (values) => { console.log('待提交的JSON内容:', values.jsonContent); // 场景1:后端要求直接传JSON对象作为请求体 try { // 把JSON字符串转成对象(如果读取时已经转了这里可以省略) const payload = JSON.parse(values.jsonContent); await axios.post('你的API端点地址', payload); alert('提交成功'); } catch (err) { console.error('提交失败', err); alert('提交失败,请检查JSON格式或网络'); } // 场景2:后端要求传multipart/form-data格式的文件 // const formData = new FormData(); // formData.append('file', values.rawFile); // await axios.post('你的API端点地址', formData, { // headers: { 'Content-Type': 'multipart/form-data' } // }); }, }); const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => { const file = event.target.files?.[0]; if (!file) return; // 存原始文件到formik状态,后续需要传FormData的时候用 formik.setFieldValue('rawFile', file); const reader = new FileReader(); reader.onload = (e) => { const fileContent = e.target?.result as string; // 选中后直接打印预览内容,满足你提交前查看的需求 console.log('选中的JSON文件内容:', fileContent); // 把内容存到formik状态,提交的时候直接取 formik.setFieldValue('jsonContent', fileContent); // 可选:提前校验JSON格式,选中即校验不用等提交报错 try { JSON.parse(fileContent); } catch (err) { alert('选择的文件不是合法的JSON格式,请重新选择'); // 清空错误的文件和内容 formik.setFieldValue('rawFile', null); formik.setFieldValue('jsonContent', null); event.target.value = ''; } }; reader.readAsText(file); } return ( <div> <form onSubmit={formik.handleSubmit}> <div> <input id="file" name="test" type="file" accept=".json" // 限制只能选JSON文件,减少格式错误 onChange={handleFileChange} /> </div> <div> {/* 可选:没有选中合法文件的时候禁用提交按钮 */} <button type="submit" disabled={!formik.values.jsonContent}> 提交 </button> </div> </form> </div > ); }
补充说明
- 给文件选择框加了
accept=".json"限制用户只能选JSON文件,减少误操作 - 加了可选的JSON格式校验逻辑,可根据自己的需求决定要不要保留
- 两种常见的提交场景都加了注释,你根据后端接口要求选择对应代码即可
内容的提问来源于stack exchange,提问作者elderlyman
相关产品推荐
相关产品推荐

