Одна из ошибок, которую я чаще всего вижу при просмотре кода React, — это неправильное использование setState.

Использование синтаксиса setState({foo: ‘bar’}) совершенно нормально, когда setState присваивается значение, которое не ссылается на текущее состояние. Проблема возникает, когда setState получает значение, такое как {count: this.state.count + 1}, которое использует текущее состояние в своих вычислениях. Прежде чем вы спросите, да, в результате этого могут возникнуть ошибки; некоторое время назад мне поручили отладить производственную систему, и я обнаружил, что причиной ошибки является неправильное использование setState.

Чтобы проиллюстрировать, как оба синтаксиса дают разные результаты, я привел пример здесь.

Чем больше вы увеличиваете интервалы в обоих примерах, тем больше становится разница между результатами. Более того, React не выдает никаких предупреждений/ошибок во время выполнения при использовании неправильного синтаксиса setState, поэтому эти ошибки часто могут оставаться незамеченными.

Почему неправильное использование setState вызывает проблему?

React setState не гарантирует немедленное срабатывание (https://reactjs.org/docs/react-component.html#setstate). В качестве оптимизации производительности React иногда группирует события setState и выполняет их вместе в более поздний момент времени. Поскольку значение {count: this.state.count + 1} оценивается во время его передачи в setState, this.state.count может быть не самым последним значением.

Чтобы проиллюстрировать это, предположим следующий сценарий:
- this.state.count имеет значение 4
- setState вызывается дважды с {count: this.state.count + 1}
- оба события задерживаются, и поэтому оба оценивают this.state.count как 4

Когда React доходит до выполнения обоих вызовов setState, результатом будет:
— Первый вызов setState оценивается как {count: 5} и, следовательно, обновляет состояние до 5
— Второй вызов setState также оценивается как {count: 5} и снова устанавливает состояние на 5

Вывод

Состояние компонента React — отличный API, который помогает инкапсулировать состояние в один компонент (более подробное обсуждение будет описано в следующем посте в блоге). Однако его функцией setState часто можно злоупотреблять, что приводит к опасным побочным эффектам. Используйте с умом!

Узнайте больше о Томе Шпитмане на tomszpytman.com