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,
}
})
}
我的申请只是一个简单的清单,看起来像这样
我在 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,
}
})
}