Реагирующие хуки: всегда ли рендеринг завершается после setState setTimeout?

#reactjs #react-hooks

#reactjs #реагирующие хуки

Вопрос:

Отказ от ответственности: я не считаю следующий подход хорошей практикой. Вероятно, я могу или должен использовать useEffect вместо этого, но я все еще хочу оценить правильность существующего кода.

В контексте хуков и функциональных компонентов верно ли следующее предположение?

 {
    setState(newValue);
    setTimeout(() => {
       //Here code expects that re-rendering of all components affected by changing state has been completed.
    }, 0);
}
  

Могу ли я быть уверен, что повторный рендеринг был завершен после setTimeout или это не гарантировано?

  1. Верно ли это предположение для текущей версии React? Если нет, есть ли какое-то конкретное поведение, нарушающее его?

  2. Могут ли на это повлиять предстоящие изменения React?

Ответ №1:

Это не гарантируется. Чтобы гарантировать, что ваше состояние изменилось, вам нужно будет использовать useEffect следующее

 useEffect(() => {
   // do something now that state has changed
}, [state])
  

Комментарии:

1. Спасибо, но есть ли конкретная причина, почему это не так, или пример, показывающий это?

2. Согласно документации React «Если вы знакомы с методами жизненного цикла класса React, вы можете представить себе useEffect Hook как componentDidMount , componentDidUpdate и componentWillUnmount вместе взятые». Таким образом, он срабатывает при обновлении компонента, гарантируя, что состояние изменилось.

3. Я знаком с useEffect этим, это хорошее решение, но мой вопрос прагматичен: учитывая, что у меня уже есть код, написанный с использованием setTimeout way, есть ли какие-либо оговорки или крайние случаи, когда он не работает описанным способом?

4. Ах, ну, я думаю, здесь было бы предостережение, если бы изменение состояния когда-либо занимало больше 0 секунд. Тогда ваш код внутри setTimeout может использовать устаревшее состояние. Так что нет, вы не можете быть уверены. И вы, вероятно, захотите провести рефакторинг, чтобы быть в безопасности.

5. @AlDuncanson это неверно. setTimeout задержка в 0 секунд не означает 0 секунд. Это означает минимум ноль секунд, без какого-либо максимального времени. Это просто означает, что этот обратный вызов будет извлечен из очереди при следующей полной очистке стека. Поскольку обратный вызов помещается в очередь после запроса обновления состояния, если все состояние обновляется синхронно, setTimeout гарантирует, что повторный рендеринг выполнен. Просто имейте в виду, поскольку значения закрытия фиксируются, использование любого значения состояния всегда будет устаревшим. Итак: это хак, используйте useEffect .