我有一个包含16个对象的数组,我在构造函数中声明它是一个状态:
this.state = {
todos:[...Array(16)].map((_, idx) => {
return {active: false, idx}
}),
}
他们的状态将通过ComponentDidMount
中的ajax调用进行更新。
componentDidMount()
{
var newTodos = this.state.todos;
axios.get('my/url.html')
.then(function(res)
{
newTodos.map((t)=>{
if (something something)
{
t.active = true;
}
else
{
t.active = false;
}
}
this.setState({
todos:newTodos,
})
}
}
然后最后,我渲染它:
render(){
let todos = this.state.todos.map(t =>{
if(t.active === true){
console.log('true'}
else{
console.log('false')
}
})
return (
<div></div>
)
}
它们在控制台中都显示为active = false,它们从不进入if条件。什么时候 我打印出渲染方法中似乎不更新的整个状态。在控制台中它表示&#34;下面的值现在刚刚更新&#34;。
我认为ComponentWillMount
中状态的更改会再次调用渲染功能吗?
如何使React接受状态的新值?
答案 0 :(得分:1)
那是因为你实际上并没有提供任何新的状态,而是改变它。
React使用浅比较是默认的(如果对象引用相同的内存地址,则对象的位置相同)。而这正是这里发生的事情:
var newTodos = this.state.todos; // newTodos === this.state.todos
this.setState({ todos:newTodos }) // replaces two equal addresses, so it simply doesn't change anything
最简单的解决方案,虽然可能不是最高效的解决方案是克隆您的待办事项数组:
var newTodos = [...this.state.todos]; // newTodos !== this.state.todos
答案 1 :(得分:1)
componentDidMount()
{
var newTodos = []; // <<<<<<<<<<<<<
axios.get('my/url.html')
.then(function(res)
{
newTodos = this.state.todos.map((t)=>{ //<<<<<<<<<<<<<<<
if (something something)
{
t.active = true;
}
else
{
t.active = false;
}
return t; //<<<<<<<<<<<<<<<<<<
} // <<<<< are you missing a semi-colon?
this.setState({
todos:newTodos,
})
}
}
map()参数(在您的代码中)是函数,而不是表达式,因此必须提供显式return
。即:
xxx.map( t => ( "return t is implicit" ) );
xxx.map( t => { "return t must be explicit" } );
而且,正如@DanielKhoroshko指出的那样,你的新变量指向this.state。当然,从来没有,永远不会直接改变this.state。由于map()
会返回一个新数组,而不会更改原始数据,这就是我们使用map()
而不是forEach()