Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 745
georgeperry Avatar asked Jan 28 '26 06:01

georgeperry


1 Answers

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.

like image 140
Anthony N Avatar answered Jan 29 '26 20:01

Anthony N