Javascript 地图函数未存储正确的值

Javascript Map Function Not Storing Correct Value

我的申请只是一个简单的清单,看起来像这样

我在 reactJS 的 map 函数中遇到了一些奇怪的行为。

import React from "react"
import "./App.css"
import todosData from "./data/todosData.js"
import TodoItem from "./components/TodoItem.js"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            todos: todosData
        }
        this.handleClick = this.handleClick.bind(this)
    }

    handleClick(id) {
        this.setState(prevState => {
            const updatedItems = prevState.todos.map(todo => {
                if (todo.id === id) {
                    todo.completed = !todo.completed
                }
                console.log(todo)
                return todo
            })
            console.log(updatedItems)
            return {
                todos: updatedItems
            }
        })
    }

    render() {
        const todoItems = this.state.todos.map(item => < TodoItem item = {
                item
            }
            key = {
                item.id
            }
            handleClick = {
                this.handleClick
            } />) 

            return ( 
              <div> 
                { todoItems } 
              </div>
            )
        }
    }
}

export default App

每当我打印出来检查值是否确实随着 console.log(todo.completed) 发生变化时,它会在控制台中打印出正确的值,但随后我尝试打印出整个列表物体,然后突然变回原来的样子。在这种情况下,我点击了选项一

这是我打印 const updatedItems 时的结果

我可以毫不费力地更改任何其他属性,我什至可以设置

todo.completed = false

并且它会将任何选中的复选框更改为未选中,只有当我尝试使用与其已存储值相反的值为其分配值时,地图功能才能正常工作

这是我从中获取数据的文件,如果有帮助的话

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

export default todosData
 handleClick(id){
this.setState(prevState => {
  const updatedItems = prevState.todos.map(todo =>{
    if(todo.id === id){
      todo.completed = !todo.completed
    }
    console.log(todo)
    return todo
  },()=>{
        console.log(updatedItems)
   })
  return{
    todos: updatedItems
  }

})
}

请试一次。您可能会在控制台中获得更新的项目

问题 - 状态突变!!

切换完成状态时,您正在改变状态对象。

handleClick(id) {
  this.setState(prevState => {
    const updatedItems = prevState.todos.map(todo => {
      if (todo.id === id) {
        todo.completed = !todo.completed; // <-- state mutation!!
      }
      return todo;
    });
    return {
      todos: updatedItems,
    };
  })
}

解决方案

您不仅需要浅复制正在更新的数组,还需要浅复制您打算更新的所有嵌套对象,这样它们就不再是浅相等的。

handleClick(id) {
  this.setState(prevState => {
    const updatedItems = prevState.todos.map(todo => {
      if (todo.id === id) {
        return {
          ...todo, // <-- copy into new object reference
          completed: !todo.completed, // <-- set new property value
        };
      }
      return todo;
    });
    return {
      todos: updatedItems,
    }
  })
}