SetState does not update state: ReactJS

I feel like I've tried everything under the sun here, but must be missing something very obvious. In addItem() function

below, I'm trying to insert a new item into the state of the array and updates, but no matter what I do, it just won't change from the original array.

When I console.log newListItems a new item is added, so everything up to this point works, this is the actual state that will not be updated. What am I missing?

addItem method:

addItem(text){
    var newListItems = this.state.listItems;
    newListItems.push(text);
    console.log(newListItems);

    this.setState = ({
        listItems : newListItems
    });

}

      

Also I am not getting an error in the console.

Complete code:

import React, { Component } from 'react';
import './App.css';
      
class ListItem extends Component{
  render(){
    return (<li>{this.props.title}</li>);
  }
}
     
class AddItem extends Component{

  handleClick(){
    this.props.addItem('blah');
  }

  render(){
    return (
      <div className="additem">
        <input type="text" className="newitemname"/>
        <span className="btn" onClick={this.handleClick.bind(this)}>Add item</span>
      </div>
    );
  }
}
    
    
class App extends Component {

  constructor(props){
    super(props);
    this.state = {
      listItems : ['Wash the dishes','Do the laundry','Something else']
    };
  }

  addItem(text){
    var newListItems = this.state.listItems;
    newListItems.push(text);
    console.log(newListItems);
    this.setState = ({
      listItems : newListItems
    });
  }

  render() {
    return (
      <div className="App">
        <ul>
          {this.state.listItems.map(function(item,index){
              return (
                  <ListItem key={index} title={item} />
              );
          })}
        </ul>
        <AddItem addItem={this.addItem.bind(this)} />
      </div>
    );
  }

}
    
    
export default App;
      

Run codeHide result


+3


source to share


1 answer


The problem is you are updating state

incorrectly, use this:

this.setState({
    listItems : newListItems
});

      

Instead of this:

this.setState = ({
    listItems : newListItems
});

      

Cause:

Because setState is not a variable, we need to call this to update the state of the value.

Check this answer for more information on setState .

Other suggestions :



When you assign any array

to any variable, the variable only gets a reference array

, meaning that any changes you make will be directly applied to the original array

. And it's not recommended to mutate the variable right away state

, so first create a copy array

with slice

, then use push

to add an item to that. Like this:

var newListItems = this.state.listItems.slice();
newListItems.push(text);
this.setState({
     listItems : newListItems
});

      

By DOC :

Never mutate this.state directly, as calling setState () may subsequently replace the mutation you made. Treat this. As if it is unchanging.

Check out a working example:

class ListItem extends React.Component{

  render(){
    return (<li>{this.props.title}</li>);
  }

}


class AddItem extends React.Component{

  handleClick(){
    this.props.addItem(this.item.value);
  }

  render(){
    return (
      <div className="additem">
        <input type="text" ref={item => this.item=item} className="newitemname"/>
        <span className="btn" onClick={this.handleClick.bind(this)}>Add item</span>
      </div>
    );
  }

}


class App extends React.Component {

  constructor(props){
    super(props);
    this.state = {
      listItems : ['Wash the dishes','Do the laundry','Something else']
    };
  }

  addItem(text){
    var newListItems = this.state.listItems.slice();
    newListItems.push(text);
    this.setState({
      listItems : newListItems
    });
  }

  render() {
    return (
      <div className="App">
        <ul>
          {this.state.listItems.map(function(item,index){
              return (
                  <ListItem key={index} title={item} />
              );
          })}
        </ul>
        <AddItem addItem={this.addItem.bind(this)} />
      </div>
    );
  }

}

ReactDOM.render(<App/>, document.getElementById('app'))
 
      

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app' />
      

Run codeHide result


+6


source







All Articles