在React中更新数组

时间:2018-01-16 23:30:52

标签: javascript ajax reactjs state

我有一个包含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;。

enter image description here

我认为ComponentWillMount中状态的更改会再次调用渲染功能吗? 如何使React接受状态的新值?

2 个答案:

答案 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()

的原因