В реакции мы обычно обновляем переменную состояния по-разному в классе и функциональном компоненте. Поскольку синтаксис обновления в этих двух типах компонентов отличается.

В компоненте класса:

// variable declaration 
this.state = { count: 0 } 
// update value 
this.setState({ count: this.state.count + 1 })

В функциональной составляющей

// variable declaration 
const [count, setCount] = useState(0); 
// update value 
setCount(count + 1);

Но в этой статье мы собираемся обсудить только компонент класса, а тема обсуждения — «Как обновить состояние на основе предыдущего состояния». Если мы будем следовать обычной процедуре, мы можем получить некоторые проблемы в некоторых сценариях. Давайте создадим этот сценарий и попробуем решить.

Итак, первый шаг — создать кнопку, а в ее событии onClick вызвать метод приращения для увеличения значения состояния счетчика.

// create a button and a onClick event 
<button onClick={() => this.increment()}>Increment</button> 
// increment method 
increment = () => { 
    this.setState({ 
        count: this.state.count + 1 
    }, () => { 
        console.log('Update value:', this.state.count) 
    }) 
}

До этого момента приложение будет работать правильно. Потому что приведенный выше сценарий очень прост. Давайте попробуем увеличить переменную count пять раз для одного события нажатия кнопки.

// create a button and a onClick event
<button onClick={() => this.incrementCountFiveTimes()}>Increment</button>
// incrementCountFiveTimes method
incrementCountFiveTimes() {
    this.increment()
    this.increment()
    this.increment()
    this.increment()
    this.increment()
}

Если мы запустим приложение, мы увидим, что increment() вызывается пять раз, а консоль записывает обновленное значение счетчика пять раз. Но если мы посмотрим внимательно, каждый раз обновленное значение счетчика будет одним и тем же, т.е. 1. И это потому, что для повышения производительности реакция может группировать несколько вызовов состояния установки в одно обновление, а обновленное значение не переносится между разными вызовами.

Решение:

Таким образом, в таком сценарии решение этой проблемы заключается в том, что всякий раз, когда нам нужно обновить состояние на основе предыдущего состояния, мы передаем функцию в качестве аргумента this.setState() вместо передачи в объект. Таким образом, обновление increment() будет выглядеть так:

increment = () => {
    this.setState((prevState) => ({
       count: prevState.count + 1
    }))
}

Это даст нам фактический результат каждый раз в журнале консоли. Потому что здесь мы увеличиваем переменную count с предыдущим состоянием, а не с текущим состоянием.

Первоначально опубликовано на https://codinghub.net.