React Native导航时重置Formik表单 解决参数变更表单值不更新问题
问题根源
- Formik 的
initialValues仅在组件首次挂载时生效,后续路由参数更新不会触发表单初始值自动重写 - 你调用
resetForm()时未传入最新的参数值,只会重置为首次加载的初始值 - 未对导航事件监听器做卸载清理,会引发重复触发、内存泄漏问题
修复方案
推荐两种可行方式,按需选择:
方案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
相关产品推荐
相关产品推荐

