无法在使用React的ToDo应用中使用ES6映射状态?

问题描述

我正在开发一个简单的Todo App,目前还无法更新App.js组件的状态。

这是我的App.js:

import React,{ Component } from "react";
import TodoItem from "./TodoItem";
import todosData from "./TodoData";

class App extends Component {
  constructor() {
    super();
    this.state = {
      loadedData: todosData,};
  }

  newChange = (id) => {
    const update = this.state.loadedData.map((todo) => {
      if (todo.id === id) {
        todo.completed = !todo.completed;
      }
      return todo;
    });
    // this is where my update variable will not update?
    console.log(update);
    this.setState({ loadedData: update });
  };

  render() {
    const todoComponent = this.state.loadedData.map((item) => (
      <TodoItem
        key={item.id}
        text={item.text}
        completed={item.completed}
        newChange={this.newChange}
      />
    ));

    return <div className="todo-list">{todoComponent}</div>;
  }
}

export default App;

这是我的TodoItem Componenet(我猜想,一旦正确传递此状态,它将正常工作):

import React from "react";

class TodoItem extends React.Component {
  render() {
    return (
      <div className="todo-item">
        <input
          type="checkBox"
          checked={this.props.completed}
          onChange={() => this.props.newChange(this.props.id)}
        />
        <p>{this.props.text}</p>
      </div>
    );
  }
}

export default TodoItem;

最后,我的数据只是由对象组成的数组:

    const todosData = [
  {
      id: 1,text: "Take out the trash",completed: true
  },{
      id: 2,text: "Grocery shopping",completed: false
  },{
      id: 3,text: "Clean gecko tank",{
      id: 4,text: "Mow lawn",{
      id: 5,text: "Catch up on Arrested Development",completed: false
  }
]

export default todosData

我最大的问题是为什么当我通过newChange()方法进行映射时,我的 update 变量不会更新吗?

当我进行console.log记录时,它会显示完全相同的数据,而我想要的属性不会得到更新?

loadedData仍然与更新完全相同。

解决方法

丹尼,您在正确的位置放console.log(update)。这样,您发现该函数实际上并未更新map函数中的现有状态。

要找出原因,您需要检查map函数内部发生的情况,第一步是测试您在其中使用的所有内容。在这种情况下,您使用的是this.props.id,则可以通过将console.log放入其值来进行检查:

  newChange = id => {
    console.log("id:",id); // NEW
    const update = this.state.loadedData.map(todo => {
      if (todo.id === id) {
        todo.completed = !todo.completed;
      }
      return todo;
    });
    // this is where my update variable will not update?
    console.log(update);
    this.setState({ loadedData: update });
  };

好吧,在这种情况下,当您尝试单击待办事项时,它将打印id: undefined,因为您实际上没有将其作为道具传递。 map函数在待办事项之间循环,但从未找到任何满足if (todo.id === id)的待办事项(因为在您的情况下它会转换为if (todo.id === undefined)

修复很简单,只需将id作为道具传递给todoComponent

  const todoComponent = this.state.loadedData.map(item => (
      <TodoItem
        id={item.id} // NEW
        key={item.id}
        text={item.text}
        completed={item.completed}
        newChange={this.newChange}
      />
    ));
,

执行以下操作时,您不小心在function findInJson(objJsonResp,key,value,aType){ if(aType=="edit"){ return objJsonResp.find(x=> x[key] == value); }else{//delete var a =objJsonResp.find(x=> x[key] == value); objJsonResp.splice(objJsonResp.indexOf(a),1); } } 处理程序中改变了状态:

newChange

相反,创建一个全新的todo.completed = !todo.completed; 对象切片:

state

或者,如果您不能使用扩展运算符(newChange = (id) => { this.setState({ loadedData: this.state.loadedData.map((todo) => ({ ...todo,completed: todo.id === id ? !todo.completed : todo.completed,})),}); }; ),请尝试以下操作:

...

您可以在React官方文档的“ The Power Of Not Mutating Data”下阅读更多内容

,

在App.js中创建ToDoItems时,您只是缺少一个道具(id)

您尝试在ToDoItem中访问它,但是您从未设置它...

因此您在App中的渲染功能应如下所示:

render() {
    const todoComponent = this.state.loadedData.map((item) => (
      <TodoItem
        key={item.id}
        id={item.id}
        text={item.text}
        completed={item.completed}
        newChange={this.newChange}
      />
    ));

    return <div className="todo-list">{todoComponent}</div>;
  }