React受控组件表单报错:TypeError: Cannot read properties of null (reading 'name')
React受控表单更新State时出现
TypeError: Cannot read properties of null (reading 'name')的原因及解决方法 问题描述
在React中创建简单受控组件表单时,onChange事件里直接执行console.log(event.target.name)能正常输出,但使用JavaScript计算属性更新state时,抛出错误:TypeError: Cannot read properties of null (reading 'name')。此前用相同逻辑创建过多个可正常运行的项目,本次问题突发。
问题原因
- React的合成事件(SyntheticEvent)采用事件池复用机制:事件处理函数同步执行完成后,React会清空事件对象的所有属性,并将其放回事件池供后续事件复用。
setContactFormValues的回调函数是异步执行的,当回调触发时,原事件对象已被React回收,event.target变为null,此时读取event.target.name自然报错。- 而开头的
console.log(event.target.name)能正常运行,是因为这行代码属于同步执行,此时事件对象还未被回收。
解决方法
方法1:提前解构事件属性(推荐)
在调用setContactFormValues之前,将event.target的name和value提取到变量中,避免后续访问已被回收的事件对象:
const handleChange = (event) => { const { name, value } = event.target; // 提前解构保存属性 setContactFormValues((prevValues) => ({ ...prevValues, [name]: value })); };
方法2:使用event.persist()保留事件对象
调用event.persist()可以阻止React回收当前事件对象,使其属性保持可用:
const handleChange = (event) => { event.persist(); // 禁用事件对象的池化复用 setContactFormValues((prevValues) => ({ ...prevValues, [event.target.name]: event.target.value })); };
修正后的完整代码
import "./Contact.css"; import React from "react"; const Contact = () => { const [contactFormValues, setContactFormValues] = React.useState({ fName: "", lName: "", email: "", phone: "", message: "", }); const handleChange = (event) => { const { name, value } = event.target; setContactFormValues((prevValues) => ({ ...prevValues, [name]: value })); }; const handleSubmit = async (event) => { event.preventDefault(); console.log(contactFormValues); } return ( <> <div className="contact-form"> <div className="contact-container"> <div className="left-section"> <div className="title"> <h1>Write Us</h1> </div> <div className="row"> <div className="contact-sub-row"> <label className="contact-label">First Name</label> <input className="contact-input" type="text" name="fName" onChange={handleChange} value={contactFormValues.fName} required /> </div> <div className="contact-sub-row"> <label className="contact-label">Last Name</label> <input className="contact-input" type="text" name="lName" onChange={handleChange} value={contactFormValues.lName} required /> </div> </div> <div className="contact-sub-row"> <label className="contact-label">Email</label> <input className="contact-input is-success" type="email" name="email" onChange={handleChange} value={contactFormValues.email} required /> </div> <div className="contact-sub-row"> <label className="contact-label">Phone</label> <input className="contact-input" type="tel" placeholder="1-123-456-7890" maxlength="20" name="phone" onChange={handleChange} value={contactFormValues.phone} required /> </div> </div> <div className="right-section"> <div className="your-message"> <label className="contact-label">Message</label> <textarea className="contact-textarea" name="message" placeholder="Write text here..." onChange={handleChange} value={contactFormValues.message} required ></textarea> </div> <div className="contact-btns"> <button className="submit-btn" onClick={handleSubmit}>SEND MESSAGE</button> </div> </div> </div> </div> </> ); }; export default Contact;
(注:恢复了代码中被注释的value属性,确保所有输入框均为标准受控组件)
内容的提问来源于stack exchange,提问作者Nishant Kumar
相关产品推荐
相关产品推荐

