Задать вопрос
Golden_Boy
@Golden_Boy

Как работает функция обновления в React?

Изучаю React и никак не могу понять как работает элементарная функция обновления, которая обычно прописывается в качестве аргумента в установщике состояния, а именно в чем принципиальная разница в подходах: setCount(count + 1) и setCount(prevCount => prevCount + 1) в следующем примере:
function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

Я примерно понимаю, что использование функции обновления prevCount => prevCount + 1 как-то связано с замыканием, но каким образом и в каком месте непонятно.
Непонятно вообще как изменяется значение count при каждом клике на кнопку, начиная с первичного рендера.
Почитал документацию, пораспрашивал ЖПТ, но тем не менее то все не очень прояснило ситуацию, т.к. замыкание довольно мутный для меня вопрос еще с чистого JS.
Мог бы кто-нибудь пошагово объяснить что происходит с состоянием компонента от рендера к рендеру?
  • Вопрос задан
  • 356 просмотров
Подписаться 1 Простой 3 комментария
Решения вопроса 1
@ParaBellum577
1. С использованием функции обратного вызова (prevState):

const increment = () => {
  setCount(prevCount => prevCount + 1);
};

В этом случае setCount принимает функцию обратного вызова, которая получает предыдущее значение состояния (prevCount) и возвращает новое значение, основанное на предыдущем. Этот подход полезен, когда новое состояние зависит от предыдущего состояния. Это также гарантирует корректность обновления состояния, даже если функция increment вызывается многократно в быстром темпе.


2. С использованием текущего значения (count):

const increment = () => {
  setCount(count + 1);
};

В этом случае setCount обновляет состояние, используя текущее значение count. Этот подход прост и будет работать в большинстве случаев. Однако он может быть проблематичным, если increment вызывается многократно в быстром темпе, так как он не гарантирует корректность обновления состояния, особенно если обновление состояния асинхронно.

Использование функции обратного вызова (первый вариант) обычно рекомендуется, если новое состояние зависит от предыдущего, и если есть потенциально множественные обновления состояния. Это помогает избежать потери обновлений состояния и гарантировать корректность данных.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Aetae
@Aetae
Тлен
Вот так утрировано выглядит внутри функция useState:
function useState(initialValue) {
  // подсчитываем вызовы useState в компоненте
  component.useStateCount++;

  // если уже был вызов этого useState(т.е. это не первая отрисовка)
  if (component.useStateCount in component.useStateCache) 
    // возвращаем результат из кэша
    return component.useStateCache[component.useStateCount];

  // если первый вызов - подготавливаем ответ вида [state, setState]
  const useStateResult = [
    initialValue, 
    function setState(callbackOrValue) {
      // если аргумент setState - функция
      if (typeof callbackOrValue === 'function') {
        // вызываем её с предыдущем значением в качестве аргумента и присваиваем результат вызова в state
        useStateResult[0] = callbackOrValue(useStateResult[0]);
      } else {
        // иначе просто присваиваем аргумент в state
        useStateResult[0] = callbackOrValue;
      }

      // вызов обновления компонента
      component.updateComounent(); 
    }
  ];

  // добавляем в кэш
  component.useStateCache[component.useStateCount] = useStateResult;

  // возвращаем
  return useStateResult;
}

Стало понятней?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы