代码在 codeSandbox 中运行良好,但在 IDE 中显示错误,如 "can't define property "email": Object is not extensible"

The code is working fine in codeSandbox, But showing error while doing in the IDE as "can't define property "email": Object is not extensible"

我正在尝试在 react.js 中实现一个简单的代码,用户可以使用表单输入数据,除非刷新页面,否则数据将显示在 table.

我已经在 Code Sandbox 中实现了一个代码,它按预期工作。然后我复制了该代码并在 IDE 中使用了它。现在,相同的代码显示错误为 ==>“TypeError:无法定义 属性“email”:对象不可扩展”。 (我用的是intellijIDE终极版)

这是沙盒的 link => Link for the code in sandbox

如果沙箱不工作,代码会自动生成 ==>

import React, {Component} from "react";

class CustomDetails extends Component {

constructor(props) {
    super(props);
    this.state = {
        items: [{email: '', country: '', new_case: '', total_case: '', total_death: ''}],
        message: ''
    }
    this.newData = React.createRef();
    this.addForm = React.createRef();

}

addData(e) {
    e.preventDefault();
    const {items} = this.state;
    
    const newData = () => ({
        email:this.addForm.email.value,
        country:this.addForm.country.value,
        new_case:this.addForm.new_case.value,
        total_case:this.addForm.total_case.value,
        total_death:this.addForm.total_death.value
    })
    const isOnTheList = items.includes(newData.country);

    if (isOnTheList) {
        this.setState(({
            message: 'This country details are already added.'
        }))
    } else {
        this.setState({
            items: [...this.state.items, newData()],
        })
    }
    this.addForm.reset();
}




render() {
    const {items, message}=this.state;
    return (
        <div>
            <div>
            
                <div>
                    <form ref={input => this.addForm = input} onSubmit={(e) => {
                        this.addData(e)
                    }}>
         
                            <label>User Email :</label><br/>
                            <input required ref={input => this.newData["email"] = input} name="email" value={this.state.items.email}
                                   type="email"
                                   placeholder="Enter email"/><br></br>

                           
                                <label>Country :</label><br/>
                                <input required ref={input => this.newData["country"] = input} name="country" value={this.state.items.country}
                                       type="text"
                                       placeholder="Enter country"/><br></br>
                           

                            
                                <label>New Cases :</label><br/>
                                <input required ref={input => this.newData["new_case"] = input}
                                name="new_case"
                                       value={this.state.items.new_case} type="text"
                                       placeholder="Enter no of new cases"/><br></br>
                           

                           
                                <label>Total cases :</label><br/>
                                <input required ref={input => this.newData["total_case"] = input}
                                name="total_case"
                                       value={this.state.items.total_case} type="text"
                                       placeholder="Enter no of total cases"/><br></br>
                           

                           
                                <label>Total death :</label><br/>
                                <input required ref={input => this.newData["total_death"] = input}
                                name="total_death"
                                       value={this.state.items.total_death} type="text"
                                       placeholder="Enter no of total deaths"/><br></br>
                            

                            <button variant="primary" type="submit">
                                Submit</button><br></br>
                       
                    </form>

                </div>
                <div>
                    
                   
                    {
                        message !== '' && <p>{this.setState.message}</p>
                    }
                    <table striped="true" bordered="true" hover="true">
                        <thead>
                        <tr>
                            <th>Email</th>
                            <th>Country</th>
                            <th>New cases</th>
                            <th>Total cases</th>
                            <th>Total deaths</th>
                        </tr>
                        </thead>
                        <tbody>
                        {items.map((item,index) => {
                            return (
                                <tr key={index}>

                                    <td>{item.email}</td>
                                    <td>{item.country}</td>
                                    <td>{item.new_case}</td>
                                    <td>{item.total_case}</td>
                                    <td>{item.total_death}</td>
                                </tr>
                            )
                        })}
                        </tbody>
                    </table>
                </div>
              
            </div>
        </div>
    )
}}export default CustomDetails;

沙盒中的输出 -->

运行 错误发生在 IDE -->

罪魁祸首是下面一行(如果你删除它,它将是下一个 input 行):-

<input required ref={input => this.newData["email"] = input} name="email" value={this.state.items.email} type="email" placeholder="Enter email"/><br></br>

在您的 ref 回调中,您将字段名称为 emailref 对象分配给 input

如果您继续 console.log(Object.isExtensible(this.newData) 在您的 render 方法中,您会看到它会显示 false。因此,您试图将 email 属性 添加到不允许的 object 中。 您的 codesandbox 默默失败 但您的 IDE 运行 在 严格模式.

您需要根据您的用例使 this.newData 等同于 {email: '', country: '', new_case: '', total_case: '', total_death: ''};,从而将 this.newData 初始化为 object。所以你的 this.newData 将不再是 React ref 而只是你的 Class.

的一个实例变量

以下是对您有帮助的 MDN 链接:-

请参阅@Drew 关于如何以更好的方式处理输入的回答。

在这种情况下使用 React 引用确实没有意义,因为您可以轻松地从表单的 onSubmit 事件对象访问字段值。

  1. 初始状态应该是一个空数组。

    this.state = {
      items: [],
    };
    
  2. addData 回调需要 class 的 this 绑定到它。

  3. addData 应该从 onSubmit 事件对象访问表单字段值。 newData 应该是您要推入 items 状态数组的表单字段值的对象。使用功能状态更新从以前的状态更新。在 items 数组中搜索现有条目时,您需要使用允许检查对象属性的数组函数,因为 Array.prototype.includes 实际上只检查引用相等性,您想要搜索具有匹配项的项目 country 属性 使用 Array.prototype.some 到 return 布尔值。

    addData = (e) => {
      e.preventDefault();
      const { items } = this.state;
    
      const newData = {
        email: e.target.email.value,
        country: e.target.country.value,
        new_case: e.target.new_case.value,
        total_case: e.target.total_case.value,
        total_death: e.target.total_death.value
      };
    
      const isOnTheList = items.some(item => item.country === newData.country);
    
      if (isOnTheList) {
        this.setState({
          message: "This country details are already added."
        });
      } else {
        this.setState((prevState) => ({
          items: [...prevState.items, newData]
        }));
      }
      e.target.reset();
    };
    
  4. 由于您的输入不受控制,您应该删除旧的“遗留”样式参考附件和 value 道具。示例:

    <input
      required
      name="email"
      type="email"
      placeholder="Enter email"
    />
    
  5. 您在尝试呈现错误消息时输入错误,{message !== "" && <p>{this.setState.message}</p>},它应该是 {message !== "" && <p>{this.state.message}</p>}

演示

完整代码:

class CustomDetails extends Component {
  constructor(props) {
    super(props);
    this.state = {
      items: [],
      message: ""
    };
  }

  addData = (e) => {
    e.preventDefault();
    const { items } = this.state;

    const newData = {
      email: e.target.email.value,
      country: e.target.country.value,
      new_case: e.target.new_case.value,
      total_case: e.target.total_case.value,
      total_death: e.target.total_death.value
    };
    const isOnTheList = items.includes(newData.country);

    if (isOnTheList) {
      this.setState({
        message: "This country details are already added."
      });
    } else {
      this.setState((prevState) => ({
        items: [...prevState.items, newData]
      }));
    }
    e.target.reset();
  };

  render() {
    const { items, message } = this.state;
    return (
      <div>
        <div>
          <div>
            <form onSubmit={this.addData}>
              <label>User Email :</label>
              <br />
              <input
                required
                name="email"
                type="email"
                placeholder="Enter email"
              />
              <br></br>

              <label>Country :</label>
              <br />
              <input
                required
                name="country"
                type="text"
                placeholder="Enter country"
              />
              <br></br>

              <label>New Cases :</label>
              <br />
              <input
                required
                name="new_case"
                type="text"
                placeholder="Enter no of new cases"
              />
              <br></br>

              <label>Total cases :</label>
              <br />
              <input
                required
                name="total_case"
                type="text"
                placeholder="Enter no of total cases"
              />
              <br></br>

              <label>Total death :</label>
              <br />
              <input
                required
                name="total_death"
                type="text"
                placeholder="Enter no of total deaths"
              />
              <br></br>

              <button variant="primary" type="submit">
                Submit
              </button>
              <br></br>
            </form>
          </div>
          <div>
            {message !== "" && <p>{this.state.message}</p>}
            <table striped="true" bordered="true" hover="true">
              <thead>
                <tr>
                  <th>Email</th>
                  <th>Country</th>
                  <th>New cases</th>
                  <th>Total cases</th>
                  <th>Total deaths</th>
                </tr>
              </thead>
              <tbody>
                {items.map((item, index) => {
                  return (
                    <tr key={index}>
                      <td>{item.email}</td>
                      <td>{item.country}</td>
                      <td>{item.new_case}</td>
                      <td>{item.total_case}</td>
                      <td>{item.total_death}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}