Ленивые начальные состояния в React

Одним из самых важных аспектов производительности в приложениях React является то, как ваши компоненты реагируют на изменения. После введения хуков в 2019 году определение компонентов с помощью функций стало новой нормой.

Они появились с интересным побочным эффектом: вся функция выполняется каждый раз, когда React обнаруживает потенциальное изменение в вашем компоненте. Раньше компоненты, определенные с помощью классов, выполняли только определенные методы, такие как методы жизненного цикла (componentDidMount и т.д.) и хорошо известный метод render.

Чтобы управлять им, React добавил замечательный хук useEffect. Однако важно помнить, что функции выполняют весь код внутри, когда их вызывают.

Инициализация состояния в React

Вы можете инициализировать состояние в React с помощью хука useState:

import { useState } from "react";

const MyComponent = () => {
  const [counter, setCounter] = useState(0);

  // Increment the given counter
  const incrementCounter = () => setCounter(counter + 1);

  return (
    <section aria-label="Counter">
      <button onClick={incrementCounter}>Increment</button>
      <output>{counter}</output>
    </section>
  );
};
Войти в полноэкранный режим Выход из полноэкранного режима

MyComponent определяет новое состояние для управления текущим значением счетчика. Следуя предыдущему утверждению, каждый раз, когда React обнаруживает потенциальное изменение, он вызывает функцию MyComponent и сравнивает результат выполнения с предыдущим состоянием приложения.

Теперь, если взглянуть на эту функцию глубже, можно обнаружить множество вызовов и определений:

  • Вызов useState.
  • Определение функции incrementCounter.
  • Вызов метода JSX под капотом

Кроме этого, есть одна маленькая деталь, о которой обычно забывают. 0 также оценивается. Итак, что произойдет, если вам нужно вызвать функцию для вычисления значения начального состояния?

Ленивое начальное состояние

Теперь давайте проверим следующий код:

import { useState } from "react";
import { initState } from "./utils";

const MyComponent = () => {
  const [value, setValue] = useState(initState());

  // ...
};
Вход в полноэкранный режим Выйти из полноэкранного режима

В этом случае useState получает в качестве параметра не статическое значение, а результат функции. Обратите внимание, что функция initState вызывается каждый раз, когда React вызывает MyComponent. Однако функция useState использует результат только один раз. После его установки следующие выполнения компонента будут отбрасывать результат initState.

В зависимости от сложности initState, он может вызвать некоторые проблемы с производительностью в MyComponent даже после первой инициализации. Чтобы избежать этого, React позволяет передать функцию, которая будет выполнена только один раз:

import { useState } from "react";
import { initState } from "./utils";

const MyComponent = () => {
  const [value, setValue] = useState(() => initState());

  // ...
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Этот трюк называется ленивой инициализацией состояния.

Не нужно быть ленивым по умолчанию

Давайте будем справедливы. К счастью, состояния инициализируются статическими значениями большую часть времени. Не все приложения смогут извлечь пользу из этой функции useState. Тем не менее, это одна из тех проблем производительности, которую трудно обнаружить, а решение довольно простое.

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

Ссылки

  • React Hooks
  • React useState Hook

Оцените статью
devanswers.ru
Добавить комментарий