Search code examples
reactjssetstate

reactjs state not being updated


in my filter() callback newList contains the correct array but state is not being updated.

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <title>list</title>
      <script src="react/react.js"></script>
      <script src="react/react-dom.js"></script>
      <script src="https://unpkg.com/[email protected]/babel.min.js"></script>
   </head>
   <body>
      <div id='container'>
      </div>
   </body>
</html>


<script type = 'text/jsx'>

class FilteredList extends React.Component{
   constructor(props){
      super(props);
      this.state={list:this.props.list};
   }

   filter(input){
      var newList = this.state.list.filter(function(item){
         return (item.search(input.target.value)!=-1);
      });
      console.log(newList);
      this.setState({list:newList});
      console.log(this.state.list);
   }

   render(){
      return(
         <div>
            <input type='text' placeholder='Filter' onChange={this.filter.bind(this)} />
            <List items={this.state.list} />
         </div>
      );
   }
}

class List extends React.Component{
   constructor(props){
      super(props);
      this.state={items:this.props.items};
   }

   render(){
      return(
         <ul>
            {this.state.items.map(function(item){
               return(<li key={item}>{item}</li>);
            })}
         </ul>

      );
   }
}

   ReactDOM.render(
      <div><FilteredList list={['anteater','bear','cat','dog','elephant','fox']} /></div>,
      document.getElementById('container')
);
</script>

Solution

  • This is because setState is asynchronous. This means that the state is not immediately updated when the line is executed, but some moment later.

    To execute code once the state has been updated, setState takes a callback as second argument :

    this.setState({list:newList}, () => console.log(this.state.list))