我有一个复选框<input type='checkbox' onClick={ this.props.isTicked.bind(this,id)} />
我还必须执行任务:
state = {
todos: [
{
id:1,
title: 'Earn 10 lvl Faceit',
completed: false
},
{
id:2,
title: 'Achieve 10 badges',
completed: false
}
]
}
因此,复选框的ID等于其任务的ID。然后我想使“ isTicked”函数使完成的值相反。我也为每项任务都有风格(对与错,这是不同的)
<div style ={this.TaskStyle()}>
<p>
<input type='checkbox' onClick={ this.props.isTicked.bind(this,id)} />
{title}
</p>
</div>
TaskStyle:
TaskStyle = () => {
if (this.props.task_value.completed) {
return {
backgroundColor: 'darkgreen',
fontFamily: 'Arial',
padding:'10px'
}
}
else {
return {
backgroundColor: 'gray',
fontFamily: 'Arial',
padding:'10px'
}
}
}
现在,这是'isTicked'的工作版本:
this.setState({todos: this.state.todos.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
})})
这是我的,我不知道为什么它不起作用....
isTicked = (id) => {
this.state.todos.forEach(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
});
}
有人可以帮我吗?)
答案 0 :(得分:1)
首先,在您的isTicked
函数中,您没有像以前的方法那样设置状态。
第二,map
返回一个新的Array,您将其设置为newState,而forEach
则没有。实际上,这是两者之间的唯一区别。
现在,当您遍历forEach
并直接更改状态时,React无法知道状态已更改,因此必须触发render
函数。因此,在其他情况下您看不到更改。另一方面,在前一种情况下,当您通过setState
修改状态时,React会依次重新渲染该组件,然后您会看到效果。
就这么简单:)
请勿直接修改状态例如,这不会重新呈现 组件:
// Wrong
this.state.comment = 'Hello';
// Instead, use setState():
// Correct
this.setState({comment: 'Hello'});
您可能想阅读以下内容:do-not-modify-state-directly
答案 1 :(得分:0)
您直接在此代码中操作状态:
isTicked = (id) => {
this.state.todos.forEach(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
});
}
可以规避Reacts状态管理,因此可以在代码中引入各种有害行为(错误)。第一个实现更好,但不是完美的,因为通过一些奇怪的巧合,您正在映射的状态可能会改变。最好使用setState
的回调语法:
this.setState(prevState => {
const newState = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed;
}
return todo;
});
return { ...prevState, newState };
});
这应该确保没有副作用发生。也许这个article对您有帮助。