MUI TextField输入时状态不更新,组件重渲染丢失状态求助
React MUI TextField输入框值无法更新、输入后失焦问题解决
问题描述
使用React + MUI开发时,TextField输入框在输入首个字符后触发组件重渲染,丢失输入状态且无法继续更新值。曾尝试用Box替代Grid、参考相关方案均未解决。
问题根源及修复方案
1. 内部定义Styled组件导致重复创建
FormContainer和StyledTextField定义在Registration组件函数内部,每次组件重渲染时都会重新生成新的组件类型,React会卸载旧组件并挂载新组件,直接导致输入框失焦、状态丢失。
修复:将Styled组件移到组件外部定义:
// 移到Registration组件外部 const FormContainer = styled("form")(({ theme }) => ({ maxWidth: 700, [theme.breakpoints.down(theme.breakpoints.values.sm)]: { maxWidth: 300 }, [theme.breakpoints.up(theme.breakpoints.values.md)]: { maxWidth: 650 } })); const StyledTextField = styled(TextField)(() => ({ "& .MuiFormLabel-asterisk": { color: "red" }, '& label.Mui-focused': { color: '#96A8AE', //Dark Grey as per SCM }, '& .MuiOutlinedInput-root': { '&.Mui-focused fieldset': { borderColor: '#96A8AE', }, }, })); const Registration = (props: any) => { // 组件内部逻辑... };
2. TextField的name属性与state字段不匹配
TextField的name属性为firstname(小写n),但state中对应的字段是firstName(大写N),导致handleChangeForm无法正确更新state,输入值无法同步。
修复:将TextField的name改为firstName:
<StyledTextField label="First Name" name="firstName" // 修正为与state字段一致 value={formData.firstName} onChange={handleChangeForm} key="firstName" size='medium' required fullWidth />
3. Grid组件嵌套属性错误
内部的Grid container额外添加了item属性,属于无效嵌套,可能影响组件渲染逻辑。
修复:移除该Grid的item属性:
<Grid container className='details__form' columnSpacing={{ xs: 2, sm: 2, md: 2 }}> <Grid item xs={6} md={6} lg={6} xl={6}> {/* TextField */} </Grid> </Grid>
修改后的完整代码
import React, { useState, ChangeEvent } from 'react'; import { Grid, TextField } from '@mui/material'; import { styled } from '@mui/material/styles'; import axios from 'axios'; import Loader from './Loader'; // 假设Loader是你的自定义组件 const FormContainer = styled("form")(({ theme }) => ({ maxWidth: 700, [theme.breakpoints.down(theme.breakpoints.values.sm)]: { maxWidth: 300 }, [theme.breakpoints.up(theme.breakpoints.values.md)]: { maxWidth: 650 } })); const StyledTextField = styled(TextField)(() => ({ "& .MuiFormLabel-asterisk": { color: "red" }, '& label.Mui-focused': { color: '#96A8AE', //Dark Grey as per SCM }, '& .MuiOutlinedInput-root': { '&.Mui-focused fieldset': { borderColor: '#96A8AE', }, }, })); const Registration = (props: any) => { const [loading, setLoading] = useState(false); const [successAlert, setSuccessAlert] = useState(false); const [formData, setFormData] = useState({ firstName: '', }); const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); submitRegister(); }; const submitRegister = async () => { setLoading(true); try { const response = await axios.post('example.com/create/user', formData); console.log(response.data.code); if (response.data.code === 200) { setSuccessAlert(true); } } catch (error) { console.log(error); } finally { setLoading(false); } }; const handleChangeForm = (e: ChangeEvent<HTMLInputElement>) => { const { name, value } = e.target; setFormData((prevFormData) => ({ ...prevFormData, [name]: value })); }; return ( <Grid container className="registration__container" spacing={2}> <Grid item xs={7} md={7} lg={7} xl={7}> <Grid className='left'> // some code here </Grid> {loading && <Loader />} </Grid> <Grid item xs={5} md={5} lg={5} xl={5} className='registration__form' key="regis-form"> <FormContainer onSubmit={handleSubmit}> <Grid container className='details__form' columnSpacing={{ xs: 2, sm: 2, md: 2 }}> <Grid item xs={6} md={6} lg={6} xl={6}> <StyledTextField label="First Name" name="firstName" value={formData.firstName} onChange={handleChangeForm} key="firstName" size='medium' required fullWidth /> </Grid> </Grid> <Grid item xs={12} className="submitbtn__wrapper"> <button type="submit">Register</button> </Grid> </FormContainer> </Grid> </Grid> ); }; export default Registration;
内容的提问来源于stack exchange,提问作者C P Verma
相关产品推荐
相关产品推荐

