数组映射函数未 return 更新项目
Array map function not return updated items
我遇到了一个奇怪的问题(至少对我来说是这样),其中 JS 数组方法 map()
没有 return 根据地图回调逻辑更新数组。
我有以下功能
1 handleChange (id){
2 this.setState((prevState)=>{
3 const todos = prevState.myTodos.map(item => {
4 if(item.id === id){
5 //console.log("ITEM.id is ",item.id,"id passed is ",id,"status is ",item.completed)
6 item.completed = !item.completed
7 }
8 //console.log("ITEM.id is ",item.id,"id passed was ",id,"new status is ",item.completed)
9 return item
10 })
11 return {myTodos : todos}
12 })
13 }
在这个函数中,我正在更新 App 对象的状态。
就在第 8 行的 return 项目之前,我可以记录输出并看到 item.completed 已更改但是当回调 returns 项目对象时,它不会将更新的项目存储在 todos
变量。
任何提示都会有很大帮助。
感谢期待
完整代码如下:
App.js 组件
import React from 'react';
//Importing components
import Todo from './components/Todo';
import './App.css';
//import todosData from './todosData';
const todosData=[ {
id:1,
text:"Take out the trash",
completed:true,
imageUrl : "https://environmentamerica.org/sites/environment/files/w-takeout-trash-wk1003mike-shutterstock_422191876.jpg"
},
{
id:2,
text:"Grocery Shopping",
completed:false,
imageUrl : "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Supermarkt.jpg/240px-Supermarkt.jpg"
},
{
id:3,
text:"Clean gecko tank",
completed:false,
imageUrl : "https://i.ytimg.com/vi/hy7eLGcCU9Q/hqdefault.jpg"
},
{
id:4,
text:"Mow Lawn",
completed:true,
imageUrl : "https://cdn.theatlantic.com/thumbor/hbIVuzfmIWAZZ_zKMj1CKSeMkAM=/507x56:2754x1320/720x405/media/img/mt/2016/07/RTR20MER/original.jpg"
}
];
class App extends React.Component {
constructor(){
super()
this.state={
myTodos : todosData,
counter : 1
}
this.handleClick = this.handleClick.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleClick (){
this.setState((prevState)=>{
const counterUpdated = prevState.counter +1
return {counter : counterUpdated}
})
}
handleChange (id){
this.setState((prevState,anything)=>{
const todos = prevState.myTodos.map(item => {
if(item.id === id){
console.log("ITEM.id is ",item.id,"id passed is ",id,"status is ",item.completed)
item.completed = !item.completed
}
console.log("ITEM.id is ",item.id,"id passed was ",id,"new status is ",item.completed)
return item
})
return {myTodos : todos}
})
}
render(){
const todoItems = this.state.myTodos.map(item=> {return <Todo key={item.id} todo={item} handleChange={this.handleChange} />})
return (
<div className="App">
<header className="App-header">
React Course from vSchool. <button onClick={this.handleClick} >Counter {this.state.counter}</button>
</header>
<main className="todo-container">
<div className="todo-list">
{todoItems}
</div>
</main>
<footer className="footer">This is copy right of no one except for images :)</footer>
</div>
);}
}
export default App;
待办事项组件:
import React, { useState } from 'react'
function Todo(props){
const [width,setWidth]=useState(140);
const [height,setHeight]=useState(85);
return(
<div className="todo-item">
<p style={{display : 'none'}}>{props.todo.id}</p>
<p>{props.todo.text}</p>
<input type="checkbox" checked={props.todo.completed}
onChange={()=>{props.handleChange(props.todo.id)}}
/>
<img
// onMouseOver={(e)=>{setWidth(250);setHeight(250);}}
// onMouseOut={(e)=>{setWidth(140);setHeight(85);}}
src={props.todo.imageUrl} width={width} height={height}/>
<hr />
</div>
);
}
export default Todo;
您可以尝试使您的 if 条件内联,这样您就不会使用 return
。类似于:
handleChange (id){
this.setState((prevState)=>{
const todos = prevState.myTodos.map(item =>
(item.id === id) ? {...item, completed: !item.completed} : item )
})
}
已编辑:此解决方案之所以有效,是因为它 returns 使用扩展语法 {...item, completed: !item.completed}
的新 JS 对象。反过来,这会强制进行新的渲染调用。
请检查此代码段
import React, { Component } from "react";
import "./styles.css";
class App extends Component {
state = {
myTodos: [
{ id: 1, title: "wake up", completed: false },
{ id: 2, title: "brush", completed: false }
]
};
handleChange = (id) => {
this.setState((prevState) => ({
myTodos: prevState.myTodos.map((todo) => {
if (todo.id === id) {
return { ...todo, completed: !todo.completed };
}
return todo;
})
}));
};
render() {
return (
<div className="App">
<h1>TODOS</h1>
{this.state.myTodos.map((todo) =>
todo.completed ? (
<del>
<p onClick={() => this.handleChange(todo.id)}>{todo.title}</p>
</del>
) : (
<p onClick={() => this.handleChange(todo.id)}>{todo.title}</p>
)
)}
</div>
);
}
}
export default App;
工作 codesandbox
问题:
- 您没有返回真实条件下的对象
我遇到了一个奇怪的问题(至少对我来说是这样),其中 JS 数组方法 map()
没有 return 根据地图回调逻辑更新数组。
我有以下功能
1 handleChange (id){
2 this.setState((prevState)=>{
3 const todos = prevState.myTodos.map(item => {
4 if(item.id === id){
5 //console.log("ITEM.id is ",item.id,"id passed is ",id,"status is ",item.completed)
6 item.completed = !item.completed
7 }
8 //console.log("ITEM.id is ",item.id,"id passed was ",id,"new status is ",item.completed)
9 return item
10 })
11 return {myTodos : todos}
12 })
13 }
在这个函数中,我正在更新 App 对象的状态。
就在第 8 行的 return 项目之前,我可以记录输出并看到 item.completed 已更改但是当回调 returns 项目对象时,它不会将更新的项目存储在 todos
变量。
任何提示都会有很大帮助。 感谢期待
完整代码如下: App.js 组件
import React from 'react';
//Importing components
import Todo from './components/Todo';
import './App.css';
//import todosData from './todosData';
const todosData=[ {
id:1,
text:"Take out the trash",
completed:true,
imageUrl : "https://environmentamerica.org/sites/environment/files/w-takeout-trash-wk1003mike-shutterstock_422191876.jpg"
},
{
id:2,
text:"Grocery Shopping",
completed:false,
imageUrl : "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Supermarkt.jpg/240px-Supermarkt.jpg"
},
{
id:3,
text:"Clean gecko tank",
completed:false,
imageUrl : "https://i.ytimg.com/vi/hy7eLGcCU9Q/hqdefault.jpg"
},
{
id:4,
text:"Mow Lawn",
completed:true,
imageUrl : "https://cdn.theatlantic.com/thumbor/hbIVuzfmIWAZZ_zKMj1CKSeMkAM=/507x56:2754x1320/720x405/media/img/mt/2016/07/RTR20MER/original.jpg"
}
];
class App extends React.Component {
constructor(){
super()
this.state={
myTodos : todosData,
counter : 1
}
this.handleClick = this.handleClick.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleClick (){
this.setState((prevState)=>{
const counterUpdated = prevState.counter +1
return {counter : counterUpdated}
})
}
handleChange (id){
this.setState((prevState,anything)=>{
const todos = prevState.myTodos.map(item => {
if(item.id === id){
console.log("ITEM.id is ",item.id,"id passed is ",id,"status is ",item.completed)
item.completed = !item.completed
}
console.log("ITEM.id is ",item.id,"id passed was ",id,"new status is ",item.completed)
return item
})
return {myTodos : todos}
})
}
render(){
const todoItems = this.state.myTodos.map(item=> {return <Todo key={item.id} todo={item} handleChange={this.handleChange} />})
return (
<div className="App">
<header className="App-header">
React Course from vSchool. <button onClick={this.handleClick} >Counter {this.state.counter}</button>
</header>
<main className="todo-container">
<div className="todo-list">
{todoItems}
</div>
</main>
<footer className="footer">This is copy right of no one except for images :)</footer>
</div>
);}
}
export default App;
待办事项组件:
import React, { useState } from 'react'
function Todo(props){
const [width,setWidth]=useState(140);
const [height,setHeight]=useState(85);
return(
<div className="todo-item">
<p style={{display : 'none'}}>{props.todo.id}</p>
<p>{props.todo.text}</p>
<input type="checkbox" checked={props.todo.completed}
onChange={()=>{props.handleChange(props.todo.id)}}
/>
<img
// onMouseOver={(e)=>{setWidth(250);setHeight(250);}}
// onMouseOut={(e)=>{setWidth(140);setHeight(85);}}
src={props.todo.imageUrl} width={width} height={height}/>
<hr />
</div>
);
}
export default Todo;
您可以尝试使您的 if 条件内联,这样您就不会使用 return
。类似于:
handleChange (id){
this.setState((prevState)=>{
const todos = prevState.myTodos.map(item =>
(item.id === id) ? {...item, completed: !item.completed} : item )
})
}
已编辑:此解决方案之所以有效,是因为它 returns 使用扩展语法 {...item, completed: !item.completed}
的新 JS 对象。反过来,这会强制进行新的渲染调用。
请检查此代码段
import React, { Component } from "react";
import "./styles.css";
class App extends Component {
state = {
myTodos: [
{ id: 1, title: "wake up", completed: false },
{ id: 2, title: "brush", completed: false }
]
};
handleChange = (id) => {
this.setState((prevState) => ({
myTodos: prevState.myTodos.map((todo) => {
if (todo.id === id) {
return { ...todo, completed: !todo.completed };
}
return todo;
})
}));
};
render() {
return (
<div className="App">
<h1>TODOS</h1>
{this.state.myTodos.map((todo) =>
todo.completed ? (
<del>
<p onClick={() => this.handleChange(todo.id)}>{todo.title}</p>
</del>
) : (
<p onClick={() => this.handleChange(todo.id)}>{todo.title}</p>
)
)}
</div>
);
}
}
export default App;
工作 codesandbox
问题:
- 您没有返回真实条件下的对象