You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native导航时重置Formik表单 解决参数变更表单值不更新问题

问题根源

  1. Formik 的 initialValues 仅在组件首次挂载时生效,后续路由参数更新不会触发表单初始值自动重写
  2. 你调用 resetForm() 时未传入最新的参数值,只会重置为首次加载的初始值
  3. 未对导航事件监听器做卸载清理,会引发重复触发、内存泄漏问题

修复方案

推荐两种可行方式,按需选择:

方案1:加key强制重挂载(最简单)

给Formik组件绑定动态key,值随路由user参数变化,key变更时Formik会自动销毁重建,直接读取最新的initialValues,无需手动处理重置逻辑。
同时修正监听器的清理逻辑:

import React, { useEffect } from 'react';
import { View } from 'react-native';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

function FormScreen({ navigation, route }) {
  const formikRef = React.useRef(); // 函数组件用useRef代替createRef
  const initialValues = { firstName: "", lastName: "", email: "" };
  
  // 合并路由里的用户参数
  const currentInitialValues = route.params?.user ? 
    {...initialValues, ...route.params.user} : initialValues;

  // 清理导航监听器
  useEffect(() => {
    const unsubscribeBlur = navigation.addListener("blur", (e) => {
      if (formikRef.current) {
        formikRef.current.resetForm();
      }
    });
    // 组件卸载时取消订阅
    return unsubscribeBlur;
  }, [navigation]);

  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      {/* 绑定动态key,user参数变化时Formik自动重挂载 */}
      <Formik
        innerRef={formikRef}
        key={route.params?.user?.id || JSON.stringify(route.params)}
        initialValues={currentInitialValues}
        validationSchema={Yup.object({
          firstName: Yup.string()
            .max(15, "Must be 15 characters or less")
            .required("Required"),
          lastName: Yup.string()
            .max(20, "Must be 20 characters or less")
            .required("Required"),
          email: Yup.string()
            .email("Invalid email address")
            .required("Required"),
        })}
        onSubmit={(values, { setSubmitting }) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 400);
        }}
      >
        <Form>
          <label htmlFor="firstName">First Name</label>
          <Field name="firstName" type="text" />
          <ErrorMessage name="firstName" />
          <label htmlFor="lastName">Last Name</label>
          <Field name="lastName" type="text" />
          <ErrorMessage name="lastName" />
          <label htmlFor="email">Email Address</label>
          <Field name="email" type="email" />
          <ErrorMessage name="email" />
          <button type="submit">Submit</button>
        </Form>
      </Formik>
    </View>
  );
}
export default FormScreen;

方案2:监听参数变化手动更新

如果不想重挂载组件,可以用useEffect监听路由参数变化,手动调用resetForm传入最新值:

useEffect(() => {
  if (formikRef.current && route.params?.user) {
    formikRef.current.resetForm({
      values: {...initialValues, ...route.params.user}
    });
  }
}, [route.params]);

内容的提问来源于stack exchange,提问作者Daniel P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 04:42:03