[英]React.js setState issue
我正在学习React.js ,但遇到一个非常奇怪的问题。 我一步一步地按照教程进行操作,当我调用this.setState
来更新this.state
object 中的笑话数组时,修改后的数组不会改变。 我想在单击复选框时将completed
的属性切换为true
/ false
。 没有控制台错误。
欢迎任何意见。
JokesTemplate.js
function JokeTemplate(props){
return (
<div className="col-md-4">
<label>Joke {props.item.id}</label>
<p>Question {props.item.desc}</p>
<p>Answer: {props.item.ans}</p>
<input type="checkbox" checked={props.item.completed} onChange={() => props.handleChange(props.item.id)} />
</div>
);
}
export default JokeTemplate;
笑话.js
import React from 'react';
import JokeTemplate from './JokeTemplate';
const jokes = [{
id:1,
desc: "Question 1",
ans: "Answer 1",
completed: false
},
{
id:2,
desc: "Question 2",
ans: "Answer 2",
completed: true
},
{
id:3,
desc: "Question 3",
ans: "Answer 3",
completed: false
}];
class Jokes extends React.Component{
constructor(){
super()
this.state = {
jokesLst: jokes
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(id){
this.setState(prevState => {
let updatedObj = prevState.jokesLst.map( item =>{
if(item.id === id){
item.completed = !item.completed;
}
return item;
})
return { jokesLst: updatedObj }
});
}
render(){
const jokesComponentArr = this.state.jokesLst.map( joke => <JokeTemplate key={joke.id} item={joke} handleChange={this.handleChange} />);
return (
<>
{jokesComponentArr}
</>
)
}
}
export default Jokes;
应用程序.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import NavBar from './components/NavBar';
import Jokes from './components/Jokes';
function App() {
return (
<div className="App">
<NavBar />
<header className="App-header">
<Jokes />
</header>
</div>
);
}
export default App;
提前致谢。
您的代码似乎仍在修改数组中的原始元素,因为它们是未按值引用的对象。 要消除此问题,您需要在prevState
的回调中复制.map()
调用中的每个元素。
在handleChange
,您可以尝试以下操作:
this.setState(prevState => {
let updatedObj = prevState.jokesLst.map(item => {
const newItem = { ...item }
if (newItem.id === id) {
newItem.completed = !newItem .completed
}
return newItem
})
return { jokesLst: updatedObj }
})
查看上面额外的const newItem = {...item }
行的区别。
或者你可以使用更短的时间:
this.setState(prevState => ({
...prevState,
jokesLst: prevState.jokesLst.map(item => ({
...item,
completed: item.id === id ? !item.completed : item.completed
}))
})
我认为您需要修改的只是 Jokes.js 中的 handleChange() 方法
我从未见过这种将逻辑用于过滤“项目”并在 this.setState() 方法内修改其“已完成”字段的方法。 但我建议你这样做。 所以在这里我们创建了一个新的 updatedObj 实例,执行所有操作已完成字段的逻辑。 最后只需调用 setState 并将 updatedObj 直接传递给它。 我在 codesandbox 上测试了这个,它可以工作。
handleChange(id) {
let updatedObj = this.state.jokesLst.map((item) => {
if (item.id === id) {
item.completed = !item.completed;
}
return item;
});
this.setState({
jokesLst: updatedObj
});
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.