React Final Form提交后先显初始值再更新?求原因与解决办法
问题原因与解决方法
原因
提交后触发Apollo的refetch query时,由于refetch是异步操作,组件会先从缓存读取旧的实体数据作为initialValues传给React Final Form,导致表单短暂回显初始值。本质是组件直接依赖Apollo查询返回的数据作为表单初始值,在refetch完成前,缓存未更新,所以表单用旧值重渲染。
解决方法
1. 让表单保留脏值,不被旧initialValues覆盖
给React Final Form添加keepDirtyOnReinitialize={true}属性,这样即使initialValues临时变回旧值,表单也会保留用户已经修改的内容,直到新数据加载完成:
<Form initialValues={yourInitialValues} keepDirtyOnReinitialize={true} onSubmit={handleSubmit} > {/* 表单字段组件 */} </Form>
2. 手动更新Apollo缓存,替代refetch query
不要依赖refetch的异步加载,而是在mutation完成后直接更新缓存,让组件立刻拿到新数据:
const [updateEntity] = useMutation(UPDATE_ENTITY_MUTATION, { update(cache, { data: { updateEntity } }) { // 手动写入更新后的实体到缓存 cache.writeQuery({ query: GET_ENTITY_QUERY, variables: { id: yourEntityId }, data: { entity: updateEntity }, }); } });
这种方式不需要等待refetch,缓存更新后组件会直接渲染新值,不会出现闪回。
3. 用提交状态隔离数据来源
在组件中维护一个isSubmitting状态,提交过程中使用表单当前的脏值作为初始值,避免旧缓存数据覆盖:
const [isSubmitting, setIsSubmitting] = useState(false); const { formState } = useFormState(); // 从React Final Form获取表单状态 const handleSubmit = async (values) => { setIsSubmitting(true); try { await updateEntity({ variables: values }); } finally { setIsSubmitting(false); } }; // 提交中用表单当前值,否则用Apollo返回的初始值 const finalInitialValues = isSubmitting ? formState.values : apolloInitialValues; <Form initialValues={finalInitialValues} keepDirtyOnReinitialize={true} onSubmit={handleSubmit} > {/* 表单字段 */} </Form>
内容的提问来源于stack exchange,提问作者Matt Jiang
相关产品推荐
相关产品推荐

