Eslint-plugin-react: 'Use callback in setState when referencing the previous state' applied outside of setting state

Created on 8 Feb 2018  路  2Comments  路  Source: yannickcr/eslint-plugin-react

Thank you for this great library!

In my project, I am getting the following error - I believe that this is being mis-applied...

59:35  error  Use callback in setState when referencing the previous state  react/no-access-state-in-setstate

The reference to line 59 is const selectedValuesCopy = { ...this.state.selectedValues } in the function below:

setSelected = function(selectedValue) {
    const selectedValuesCopy = { ...this.state.selectedValues }

    if (Array.isArray(selectedValue)) {
        for (let i = 0; i < selectedValue.length; i++) {
            const model = getModel(selectedValue[i])
            selectedValuesCopy[model] = selectedValue[i]
        }
    } else {
        const model = getModel(selectedValue)
        selectedValuesCopy[model] = selectedValue
    }

    this.setState({ "selectedValues": selectedValuesCopy })
}

Not only am I not calling setState() on that line, but copying the state like this is, in my understanding, a very appropriate way to reference the previous state. Can you advise?

Most helpful comment

Its because you are taking a copy of the state, modifying it and setting it again which, due to setState being async, is bad as you may overwrite state. Best to do below, using a updater function in setState.

setSelected = function(selectedValue) {
  this.setState((prevState) => {
    const selectedValuesCopy = { ...prevState.selectedValues }
      if (Array.isArray(selectedValue)) {
        for (let i = 0; i < selectedValue.length; i++) {
          const model = getModel(selectedValue[i])
          selectedValuesCopy[model] = selectedValue[i]
      }
    } else {
      const model = getModel(selectedValue)
      selectedValuesCopy[model] = selectedValue
    }
    return { "selectedValues": selectedValuesCopy })
  })
}

See reactjs.org for more information around the updater function.

All 2 comments

Its because you are taking a copy of the state, modifying it and setting it again which, due to setState being async, is bad as you may overwrite state. Best to do below, using a updater function in setState.

setSelected = function(selectedValue) {
  this.setState((prevState) => {
    const selectedValuesCopy = { ...prevState.selectedValues }
      if (Array.isArray(selectedValue)) {
        for (let i = 0; i < selectedValue.length; i++) {
          const model = getModel(selectedValue[i])
          selectedValuesCopy[model] = selectedValue[i]
      }
    } else {
      const model = getModel(selectedValue)
      selectedValuesCopy[model] = selectedValue
    }
    return { "selectedValues": selectedValuesCopy })
  })
}

See reactjs.org for more information around the updater function.

@nicholas-l Thank you so much, that's obviously my mistake. Really appreciate you taking the time to school me on this.

Was this page helpful?
0 / 5 - 0 ratings