How to Set State with arguments passed to a function in React

10,780

The issue might be that you are expecting this.setState to be synchronous. See the documentation here.

Take a look at this CodeSandbox demo. this.setState accepts a callback as the second argument. This callback is invoked after this.setState has completed.

Notice how in the console.log output, we can see the old and new state values.

Share:
10,780
georgeperry
Author by

georgeperry

Trying to make it in the big bad world of software development! Team JS

Updated on June 05, 2022

Comments

  • georgeperry
    georgeperry almost 2 years

    I'm trying to pass an array (titles) from a child component to the parent, then set the state of the parent with the array. However, when handling the change in the increaseReads() method, I cannot change the articlesRead state

    You will see two console.log() statements; the first one is successfully logging the titles but the second is logging an empty array - the previous state

    The Child:

    export class Publication extends React.Component {
      constructor() {
        super();
        this.state = {
          items: []
        };
      }
    
      componentDidMount() {
        fetch(this.props.url)
        .then(response => {
          return response.json();
        }).then(({ items })=> {
          this.setState({ items });
        });
      }
    
      handleClick () => {
        this.props.openArticle();
      }
    
    
      render() {
        return (
          <div className='publication'>
            <h4>{this.props.name}</h4>
            <ul>
              {this.state.items.map(item => (
               <li><a href={item.link} target='_blank' onClick={this.handleClick}>{item.title}</a></li>
              ))}
            </ul>
          </div>
        );
      }
    }
    

    The Parent:

    export class Latest extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          totalReads: 0,
          articlesRead: []
        };
      }
    
      handleChange = () => {
        this.props.increaseTotal();
      }
    
      increaseReads(titles) {
        this.setState({
          totalReads: this.state.totalReads + 1,
          articlesRead: titles
        })
    
        // Won't log correctly
        console.log(this.state.articlesRead);
    
        this.handleChange();
      }
    
      render() {
        return (
          <div className='container'>
            <Publication total={(titles) => {this.increaseReads(titles)}} name='Free Code Camp' api={'https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fmedium.freecodecamp.org%2Ffeed%2F'}/>
            <Publication total={() => {this.increaseReads()}} name='Code Burst' api={'https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fcodeburst.io%2Ffeed%2F'}/>
            <Publication total={() => {this.increaseReads()}} name='JavaScript Scene' api={'https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fmedium.com%2Ffeed%2Fjavascript-scene%2F'}/>
            <Publication total={() => {this.increaseReads()}} name='Hacker Noon' api={'https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fhackernoon.com%2Ffeed'}/>
          </div>
        )
      }
    }
    

    I'm sure it is something small, but any help would be greatly appreciated!

  • georgeperry
    georgeperry about 6 years
    Thanks! This worked! I added a callback function to the end of this.setState that revealed my state was in fact updating correctly