React Formik中为已有对象数组新增属性赋值接口数据失败怎么办
问题根因
你的代码不生效核心是违反了Formik的状态更新规则:
- Formik的表单状态遵循不可变更新原则,直接通过
myInfo[idx].vals = myData突变(mutate)原始状态对象,不会触发Formik的状态校验和重渲染,新属性自然不会同步到表单值里 - 你没有调用Formik官方提供的状态更新方法,直接修改游离的变量引用,不会被Formik的状态管理捕获
- 额外隐患:直接用数组索引匹配请求结果,如果接口返回顺序和请求发送顺序不一致,会出现vals属性赋值错位的问题
修复方案
首先从Formik实例中取出setFieldValue方法(无论你用useFormik钩子还是<Formik>组件的render props都可以拿到这个方法),所有表单值的更新都通过这个方法执行,并且更新时要生成新的数组/对象,不要直接修改原状态。
完整实现代码
// 如果你用useFormik初始化表单 const formik = useFormik({ initialValues: { // 其他表单字段... myInfo: [ { myId: 0, myName: "Name A", defaultVal: 2 }, { myId: 1, myName: "Name B", defaultVal: 4 } ] }, // 你的校验规则、提交逻辑等其他配置... }); const getAdditionalData = async (id) => { try { const response = await fetch(`http://localhost:3000/more-data/${id}`); const myData = await response.json(); // 不可变更新:通过myId匹配对应项,避免请求顺序错乱导致赋值错位 const updatedMyInfo = formik.values.myInfo.map(item => { if (item.myId === id) { // 复制原有项属性,新增vals字段 return { ...item, vals: myData }; } return item; }); // 调用Formik的更新方法同步新值到表单状态 formik.setFieldValue('myInfo', updatedMyInfo); } catch (err) { console.error(err.message); } }; useEffect(() => { // 不需要返回值的遍历用forEach即可,不需要用map formik.values.myInfo.forEach((info) => { getAdditionalData(info.myId); }); }, []);
如果你用的是<Formik>组件嵌套写法,直接从组件的render props中解构出setFieldValue和values替换上述代码里的formik.setFieldValue、formik.values即可,逻辑完全一致。
提示:所有Formik表单值的修改都不要直接操作
values里的原始对象,必须生成新的引用(新对象/新数组)后通过官方提供的setFieldValue、setValues等方法更新,否则Formik无法检测到状态变化,就会出现改了值但不生效、视图不更新的问题。
内容的提问来源于stack exchange,提问作者ArthurJ
相关产品推荐
相关产品推荐

