TypeError: Cannot read property 'name' of undefined in react js

TypeError: Cannot read property 'name' of undefined in react js

我是新手。问题是当我在 map 函数中传递数组对象时抛出以下错误。

这是我定义数组对象的构造函数。

constructor() {
    super();
    this.state = {
      data: [
        {
          name: "",
          completed: false,
        },
      ],
      checkValue: false,
    };
  }

现在我想知道实际的问题是来自 handleChange 和 handleSubmit 函数,因为我不知道在这里写什么

handleChange = (e) => {
    e.preventDefault();

    this.setState({ name: e.target.value });
  };

  handleSubmit = (e) => {
    e.preventDefault();

    this.setState({
      data: [...this.state.data, this.state.data.name],
    });
    e.target.reset();
  }; 

这是映射函数,我在其中映射了列表项和复选框、删除按钮(我只是在将输入保存在列表项数组中时遇到了问题,这些复选框和删除按钮工作正常)

render() {
    return (
      <Fragment>
        <h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
          todos
        </h1>
        <form className="todo-form" onSubmit={this.handleSubmit}>
          <label className="label" onClick={this.handleCheck}>
            ^
          </label>
          <input
            autoFocus
            type="text"
            onChange={this.handleChange}
            className="new-todo shadow-lg p-3 mb-5 bg-white"
            placeholder="What needs to be done?"
          />
          <ul className="list-group">
            {this.state.data.map((data, index) => {
              return (
                <div key={"todo-" + index} className="div-list">
                  <input
                    className="check"
                    onChange={this.handleCheckChange}
                    type="checkbox"
                    style={{
                      cursor: "pointer",
                    }}
                    defaultChecked={this.state.data.completed}
                  />
                  <li
                    className="list-group-item disabled w-50 p-3 mx-auto"
                    style={{
                      textDecoration:
                        this.state.data.completed && "line-through",
                    }}
                  >
                    {data.name}
                  </li>
                  <button
                    onClick={() => this.handleDelete(index)}
                    type="button"
                    className="close"
                    aria-label="Close"
                  >
                    <span aria-hidden="true">&times;</span>
                  </button>
                </div>
              );
            })}
          </ul>
          {this.state.data.length > 0 && (
            <Display noOfTodos={this.state.data.length} />
          )}
          {this.state.checkValue && <Clear />}
        </form>
      </Fragment>

我知道上面的代码是不完整的,因为我只想知道如何在列表组中显示该名称元素,没有别的所以忽略其余代码

提前致谢!!

主页组件

import React, { Component, Fragment } from "react";
import Clear from "./clear";
import Display from "./display";

class MainPage extends Component {
  constructor() {
    super();
    this.state = {
      data: [
        {
          name: "",
          completed: false,
        },
      ],
      checkValue: false,
    };
  }

  handleChange = (e) => {
    e.preventDefault();

    this.setState({ name: e.target.value });
  };

  handleSubmit = (e) => {
    e.preventDefault();

    this.setState({
      data: [...this.state.data, { name: e.target.value, completed: false }],
    });
    e.target.reset();
  };

  handleDelete = (index) => {
    const newList = [...this.state.data];
    newList.splice(index, 1);

    this.setState({ data: newList });
  };

  handleCheck = (e) => {
    e.preventDefault();
  };

  handleCheckChange = () => {
    const { checkValue } = this.state;

    this.setState({ checkValue: !checkValue });
  };

  render() {
    return (
      <Fragment>
        <h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
          todos
        </h1>
        <form className="todo-form" onSubmit={this.handleSubmit}>
          <label className="label" onClick={this.handleCheck}>
            ^
          </label>
          <input
            autoFocus
            type="text"
            onChange={this.handleChange}
            className="new-todo shadow-lg p-3 mb-5 bg-white"
            placeholder="What needs to be done?"
          />
          <ul className="list-group">
            {this.state.data.map((data, index) => {
              return (
                <div key={"todo-" + index} className="div-list">
                  <input
                    className="check"
                    onChange={this.handleCheckChange}
                    type="checkbox"
                    style={{
                      cursor: "pointer",
                    }}
                    defaultChecked={this.state.data.completed}
                  />
                  <li
                    className="list-group-item disabled w-50 p-3 mx-auto"
                    style={{
                      textDecoration:
                        this.state.data.completed && "line-through",
                    }}
                  >
                    {data.name}
                  </li>
                  <button
                    onClick={() => this.handleDelete(index)}
                    type="button"
                    className="close"
                    aria-label="Close"
                  >
                    <span aria-hidden="true">&times;</span>
                  </button>
                </div>
              );
            })}
          </ul>
          {this.state.data.length > 0 && (
            <Display noOfTodos={this.state.data.length} />
          )}
          {this.state.checkValue && <Clear />}
        </form>
      </Fragment>
    );
  }
}

export default MainPage;

显示组件

import React, { Component } from "react";

class Display extends Component {
  render() {
    return (
      <div>
        <p className="para">{this.props.noOfTodos} items left</p>
        <button type="button" className=" all btn btn-light p-1 mr-3">
          All
        </button>
        <button type="button" className=" act btn btn-light p-1 mr-3">
          Active
        </button>
        <button type="button" className=" comp btn btn-light p-1">
          Completed
        </button>
      </div>
    );
  }
}

export default Display;

清除组件

import React, { Component } from "react";

class Clear extends Component {
  render() {
    return (
      <button type="button" className="clr btn btn-light p-1">
        Clear completed
      </button>
    );
  }
}

export default Clear;

基本上你做错的是错误地访问数据数组和错误地设置状态。我已经修复了这两个部分。 您的 MainPage 组件代码应该是这样的...

import React, { Component, Fragment } from "react";
import Clear from "./clear";
import Display from "./display";

class MainPage extends Component {
  constructor() {
    super();
    this.state = {
      data: [
        {
          name: "first todo",
          completed: false
        }
      ],
      checkValue: false
    };
  }

  handleChange = (e) => {
    e.preventDefault();

    this.setState({ name: e.target.value });
  };

  handleSubmit = (e) => {
    e.preventDefault();
    this.setState({
      data: [
        ...this.state.data,
        {
          name: this.state.name,
          completed: false
        }
      ]
    });
    e.target.reset();
  };

  handleDelete = (index) => {
    const newList = [...this.state.data];
    newList.splice(index, 1);
    this.setState({ data: newList });
  };

  handleCheck = (e) => {
    e.preventDefault();
  };

  handleCheckChange = () => {
    const { checkValue } = this.state;

    this.setState({ checkValue: !checkValue });
  };

  render() {
    console.log(this.state.data);
    return (
      <Fragment>
        <h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
          todos
        </h1>
        <form className="todo-form" onSubmit={this.handleSubmit}>
          <label className="label" onClick={this.handleCheck}>
            ^
          </label>
          <input
            autoFocus
            type="text"
            onChange={this.handleChange}
            className="new-todo shadow-lg p-3 mb-5 bg-white"
            placeholder="What needs to be done?"
          />
          <ul className="list-group">
            {this.state.data.map((data, index) => {
              return (
                <div key={"todo-" + index} className="div-list">
                  <input
                    className="check"
                    onChange={this.handleCheckChange}
                    type="checkbox"
                    style={{
                      cursor: "pointer"
                    }}
                    defaultChecked={this.state.data.completed}
                  />
                  <li
                    className="list-group-item disabled w-50 p-3 mx-auto"
                    style={{
                      textDecoration:
                        this.state.data.completed && "line-through"
                    }}
                  >
                    {data.name}
                  </li>
                  <button
                    onClick={() => this.handleDelete(index)}
                    type="button"
                    className="close"
                    aria-label="Close"
                  >
                    <span aria-hidden="true">&times;</span>
                  </button>
                </div>
              );
            })}
          </ul>
          {this.state.data.length > 0 && (
            <Display noOfTodos={this.state.data.length} />
          )}
          {this.state.checkValue && <Clear />}
        </form>
      </Fragment>
    );
  }
}

export default MainPage;

您可以在此处的 CodeSandbox 中查看。 https://codesandbox.io/s/happy-snow-dqbbc?file=/src/MainPage.js:0-3021

试试这个:

 data: [...this.state.data, this.state.data[0].name]