Одна из ошибок, которую я чаще всего вижу при просмотре кода 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