Search code examples
javascriptreactjssetstate

ReactJS setState doesn't work with a parameter/argument from a method/function


I can't seem to get setState to change (mutate) a value coming from an argument or parameter of a method/function. At least, it doesn't work on the first call. I have to call setState twice before the value changes.

import React from 'react'

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      testItem: 'originalValue'
    }
  }

  updateState(input) {
    this.setState({
      testItem: input
    },
      console.log(this.state.testItem) // displays 'originalValue' instead of 'newValue!', at least on the first call
    )
  }

  render() {
    return (
      <button onClick={() => this.updateState('newValue!')}>
        Change State
        </button>
    )
  }
}

export default App

The state of 'testItem' should change from 'originalValue' to 'newValue!' (taken from the argument 'input' in the method 'updateState(input)') when the button is clicked, but it doesn't change on the first click (even when using a callback in setState). It only changes when I click on the button a second time. Why is this?


Solution

  • Right now, console.log gets invoked straight away with the current state, which is the initial state you set because setState is asynchronous (i.e state is not immediately updated with the latest change).

    Because of this, we need to defer the invocation of console.log by wrapping it in a function. We do this so it can be invoked at a later time by the setState as opposed to every time you call setState

    To do this, you pass a callback function that will be executed after your setState has been performed.

    this.setState({ testItem: input}, () => console.log(this.state))