You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 00:59:07