React配合MUI与Formik开发表单,输入字符后输入框失焦如何解决?
问题原因
- 你将
FieldStack组件定义在了FormComponent函数内部,每次表单值变化触发FormComponent重渲染时,都会生成全新的FieldStack函数实例,React会判定为不同类型的组件,直接销毁旧组件实例、挂载新实例,导致输入框丢失焦点。 - 你给
Stack组件绑定了每次渲染都会重新生成的uuid作为key,进一步强制触发了组件的销毁重建,属于反效果操作。
解决方案
推荐方案:将FieldStack移到组件外部定义
Formik提供了useFormikContext钩子可以直接从上下文获取表单实例,完全不会丢失initialValues等数据,组件只初始化一次,不会频繁销毁重建:
import { Form, FormikProvider, useFormik, useFormikContext } from "formik"; import { TextField, Stack } from "@mui/material"; // 在FormComponent外部定义,全局仅初始化一次 const FieldStack = (props) => { const { getFieldProps } = useFormikContext(); return ( <Stack direction={{ xs: "column", md: "row" }} sx={{ mb: 3 }} spacing={2} > <TextField fullWidth label={props.name} {...getFieldProps(props.data)} /> </Stack> ) } export default function FormComponent() { const formik = useFormik({ enableReinitialize: false, initialValues: { name: "Jordan Spikes", description: "Just a regular dude", state: "Alabama", country: "USA" }, onSubmit: (values) => { // 处理提交逻辑 console.log(values) } }); const { handleSubmit } = formik; return ( <FormikProvider value={formik}> <Form autoComplete="off" noValidate onSubmit={handleSubmit}> <h3>Form</h3> <FieldStack name="Name" data="name" /> <FieldStack name="Description" data="description" /> <FieldStack name="State" data="state" /> <FieldStack name="Country" data="country" /> </Form> </FormikProvider> ); }
临时兼容方案:将FieldStack作为渲染函数调用
如果不想调整组件定义位置,可以把组件调用改为函数执行,避免React将其识别为独立组件实例触发销毁重建:
// 原有FieldStack定义保留在FormComponent内部 // 渲染时改为函数执行写法 {FieldStack({name:"Name", data:"name"})} {FieldStack({name:"Description", data:"description"})} {FieldStack({name:"State", data:"state"})} {FieldStack({name:"Country", data:"country"})}
避坑提示
- 不要给稳定渲染的元素/组件使用随机生成的uuid作为key,key必须是稳定不变的唯一标识,随机key只会强制触发组件重建,加重问题。
- autoFocus会在组件挂载时自动触发聚焦,配合组件频繁重建的问题就会出现无限循环的异常。
内容的提问来源于stack exchange,提问作者My Name is Ratna
相关产品推荐
相关产品推荐

