React-Final-Form基于服务端数据动态生成表单时动态设置initialValues
编辑补充:下述方案已验证可行
此前问题出在值的点号路径写法上,字段路径必须正确转换为与工具changeValue方法一致的对象结构才可正常生效。
问题背景
我使用final-form实现表单,该表单部分模块需要基于服务端加载的数据模板、数据内容动态生成。
目前已经实现自定义mutator,在表单生成完成、服务端数据加载完毕后设置对应字段值,mutator本身运行正常。但存在一个问题:部分动态表单模块(例如下拉框初始值对应模块、用户选择下拉选项后异步加载生成的表单模块)加载渲染完成后,如果不更新initialValues,用户还没触碰交互表单,就会提前进入脏状态。
核心诉求:是否可以在模板/异步数据加载完成后动态设置initialValues,既避免表单未交互就进入错误的pristine/dirty状态,又不影响表单内其他已存在的字段值与之前已配置的initialValues?
说明:以下代码仅为父组件声明的表单(已集成自定义mutator)中使用的子组件简化示例,原始业务代码复杂度较高无法完整展示,示例可能存在语法瑕疵、复选框适配不完善等问题,无需过度关注这部分内容,mutator本身运行正常,重点关注
initialValues动态设置相关逻辑即可。
interface Props { fieldName: string; fieldType: "checkbox" | "text"; fieldValue: string | boolean; } function DynamicFormField({ fieldName, fieldType, fieldValue }: Props) { const form = useForm(); useEffect(() => { // 尝试过的无效写法1:直接修改原initialValues对象引用 const initialValues = form.getState().initialValues; initialValues[fieldName] = fieldValue; form.setConfig("initialValues", initialValues); // 尝试过的无效写法2:浅拷贝initialValues后修改 const initialValuesCopy = { ...form.getState().initialValues }; initialValuesCopy[fieldName] = fieldValue; form.setConfig("initialValues", initialValuesCopy); form.mutators.setValue(fieldName, fieldValue); }, [fieldName, fieldValue] ) return ( <Field name={fieldName}> {({ input }) => ( fieldType === "checkbox" ? <input {...input} type="checkbox" /> : <input {...input} type="text" /> )} </Field> ) }
验证可行的修复方案
之前的错误写法(读取initialValues作为修改基准):
... const initialValues = form.getState().initialValues; initialValues[fieldName] = fieldValue; form.setConfig("initialValues", initialValues); ...
替换为以下写法即可正常生效:
... const initialValues = form.getState().values; initialValues[fieldName] = fieldValue; form.setConfig("initialValues", initialValues); ...
修改逻辑:
- 不再从
form.getState().initialValues取基准值,改为读取form.getState().values拿到当前表单的实时填写值,作为新的initialValues基准 - 该写法可以完整保留表单当前已有的填写值,不会触发表单重新初始化逻辑,同时能正确更新初始值标记,避免动态加载的字段未经过用户交互就被判定为脏值。
内容的提问来源于stack exchange,提问作者Fis
相关产品推荐
相关产品推荐

