React函数组件报错:Cannot assign to read only property 'addContactHandler' of object '#<Object>' 求助
解决React函数组件中子向父传递数据的TypeError问题
你遇到的TypeError: Cannot assign to read only property 'addContactHandler' of object '#<Object>'错误,根源是你在子组件里错误地给props属性赋值,而不是调用它。React里子组件接收的props是只读的,不能直接修改,这是单向数据流的核心规则之一。
下面是具体的修正步骤和完整代码:
1. 修正子组件AddContact.js的逻辑
你需要把三个输入字段的值组装成一个完整的联系人对象,然后调用父组件传来的addContactHandler函数,把这个对象作为参数传递过去,而不是给函数赋值。
修正后的AddContact.js:
import React,{useState} from 'react' const AddContact =(props) =>{ const [contactName, setContactName] = useState(""); const [contactEmail, setContactEmail] = useState(""); const [contactPhone, setContactPhone] = useState(""); const handleAdd = (e) => { e.preventDefault(); // 校验必填字段 if(contactName === "" || contactEmail === ""|| contactPhone === "") { alert("All fields are mandatory!!"); return; } // 组装完整的联系人数据对象 const newContact = { name: contactName, email: contactEmail, phone: contactPhone }; // 调用父组件的函数,传递数据 props.addContactHandler(newContact); // 清空输入框 setContactName(""); setContactEmail(""); setContactPhone(""); } // 补充完整的JSX渲染(你之前的代码没贴全,这里是示例) return ( <form onSubmit={handleAdd}> <div> <label>Name:</label> <input type="text" value={contactName} onChange={(e) => setContactName(e.target.value)} placeholder="Enter name" /> </div> <div> <label>Email:</label> <input type="email" value={contactEmail} onChange={(e) => setContactEmail(e.target.value)} placeholder="Enter email" /> </div> <div> <label>Phone:</label> <input type="tel" value={contactPhone} onChange={(e) => setContactPhone(e.target.value)} placeholder="Enter phone" /> </div> <button type="submit">Add Contact</button> </form> ); } export default AddContact;
2. 修正父组件App.js的状态更新逻辑
原来的addContactHandler里有个错误:ContactEmail : props.ContactEmail,这里的props是App组件自己的props,根本不是子组件传来的数据。现在子组件已经传递了完整的联系人对象,只需要给它加上id,然后更新状态即可。另外推荐用函数式更新来确保状态的正确性。
修正后的App.js相关代码:
import React, { useState } from 'react'; import AddContact from './AddContact'; const App = () => { const [contacts, setContacts] = useState([]); const addContactHandler = (newContact) => { // 用函数式更新,基于最新的状态来添加新联系人 setContacts(prevContacts => [ ...prevContacts, // 给新联系人添加唯一id,然后展开所有字段 { id: Math.random() * 1000, ...newContact } ]); console.log('Added contact:', newContact); } return ( <div className="app"> <h1>My Contacts</h1> <AddContact addContactHandler={addContactHandler} /> {/* 渲染联系人列表 */} <div className="contacts-list"> {contacts.map(contact => ( <div key={contact.id} className="contact-card"> <h3>{contact.name}</h3> <p>Email: {contact.email}</p> <p>Phone: {contact.phone}</p> </div> ))} </div> </div> ); } export default App;
关键知识点总结
- props是只读的:子组件永远不能修改props,只能调用props里的函数来向父组件传递数据。
- 传递完整对象更高效:把多个字段整合成一个对象传递,比单独传每个字段更清晰,也便于后续扩展字段。
- 函数式状态更新:当新状态依赖于旧状态时,用
setState(prevState => ...)的形式,避免闭包导致的状态不一致问题。
内容的提问来源于stack exchange,提问作者Neha Mohammad niyaz
相关产品推荐
相关产品推荐

