React - это библиотека для создания интерфейсных представлений. Он имеет большую экосистему библиотек, которые с ним работают. Кроме того, мы можем использовать его для улучшения существующих приложений.

В этой статье мы рассмотрим хуки useCallback, useMemo, useRef и useImperativeHandle.

useCallback

Мы можем использовать хук useCallback, чтобы вернуть мемоизированный обратный вызов.

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

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

Например, мы можем использовать его следующим образом:

function App() {
  const [count, setCount] = React.useState(0);
  const memoizedIncrement = React.useCallback(() => {
    setCount(count => count + 1);
  }, [setCount]);
  const memoizedDecrement = React.useCallback(() => {
    setCount(count => count - 1);
  }, [setCount]);
  return (
    <>
      Count: {count}
      <button onClick={memoizedDecrement}>Decrement</button>
      <button onClick={memoizedIncrement}>Increment</button>
    </>
  );
}

В приведенном выше коде мы использовали ловушку useCallback для создания двух новых функций, позволяющих обновить count. У нас есть setCount(count => count + 1) и setCount(count => count — 1) в обратном вызове useCallback.

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

Затем в onClick обработчиках мы используем их как обычно.

Каждое значение, указанное в обратном вызове, также должно появиться в массиве зависимостей.

useMemo

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

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

Следовательно, мы должны написать код, который работает с useMemo, а затем добавить его для оптимизации производительности.

Например, мы можем использовать его следующим образом:

function App() {
  const [count, setCount] = React.useState(0);
  const doubleCount = React.useMemo(() => 2 * count, [count]);
  return (
    <>
      Double Count: {doubleCount}
      <button onClick={() => setCount(oldCount => oldCount - 1)}>
        Decrement
      </button>
      <button onClick={() => setCount(oldCount => oldCount + 1)}>
        Increment
      </button>
    </>
  );
}

В приведенном выше коде мы используем хук useMemo, передавая функцию, которая возвращает 2 раза count, и передаем массив с count внутри в качестве второго аргумента.

useMemo кэширует значение doubleCount, пока count не изменится.

Затем мы передаем функции для вызова setCount в onClick свойствах кнопок.

Наконец, мы отображаем значение doubleCount на экране, которое обновляется, когда мы нажимаем на кнопки.

useRef

Хук useRef возвращает изменяемую ссылку, свойство current которой инициализировано переданным аргументом. Возвращенный объект будет сохраняться в течение всего времени существования компонента.

Например, мы можем использовать его следующим образом:

function App() {
  const inputEl = React.useRef(null);
  React.useEffect(() => {
    inputEl.current.focus();
  }, []);
  return (
    <>
      <input ref={inputEl} type="text" />
    </>
  );
}

В приведенном выше коде мы создали inputEl ref, вызвав useRef со значением null.

Затем, как только мы передаем inputEl как ref ввода, мы устанавливаем inputEl.current как объект DOM входного элемента.

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

Его можно использовать для хранения любого изменяемого значения. useRef создает простой объект Javascript.

Единственная разница между useRef() и созданием самого { current: ... } объекта состоит в том, что useRef будет давать нам один и тот же объект ref при каждом рендеринге.

useRef не уведомляет нас об изменении содержания.

useImperativeHandle

useImperativeHandle настраивает значение экземпляра, которое предоставляется родительским компонентам при использовании ref.

Например, мы можем использовать его следующим образом:

function Button(props, ref) {
  const buttonRef = React.useRef();
  React.useImperativeHandle(ref, () => ({
    focus: () => {
      buttonRef.current.focus();
    }
  }));
  return <button ref={buttonRef}>Button</button>;
}
Button = React.forwardRef(Button);
function App() {
  const buttonRef = React.useRef(null);
  React.useEffect(() => {
    buttonRef.current.focus();
  }, []);
  return (
    <>
      <Button ref={buttonRef} />
    </>
  );
}

В приведенном выше коде мы имеем:

React.useImperativeHandle(ref, () => ({
    focus: () => {
      buttonRef.current.focus();
    }
  }));

для настройки метода focus для вызова buttonRef.current.focus();.

Затем мы передаем buttonRef из Button в button ref следующим образом:

<button ref={buttonRef}>Button</button>;

Затем, чтобы сделать ссылку доступной для App, мы запускаем:

Button = React.forwardRef(Button);

Затем в App запускаем:

const buttonRef = React.useRef(null);

для создания ссылки и:

<Button ref={buttonRef} />

установить buttonRef на наш открытый Button buttonRef после вызова forwardRef, чтобы открыть его App.

Затем запускаем:

React.useEffect(() => {
    buttonRef.current.focus();
  }, []);

чтобы сфокусировать Button компонент button при App первом рендеринге.

Заключение

Мы можем использовать хук useCallback, чтобы вернуть мемоизированный обратный вызов, который мы можем вызвать. Он принимает обратный вызов в качестве аргумента и массив зависимостей, на которые ссылается обратный вызов в качестве второго аргумента.

useMemo кэширует вычисленные значения. Он принимает функцию, которая возвращает значение в качестве первого аргумента, и массив значений, от которых функция зависит, в качестве второго аргумента.

useRef возвращает изменяемый объект, свойство current которого инициализировано начальным значением и может быть передано в свойство ref элемента, чтобы установить current в элемент DOM.

useImperativeHandle настраивает поведение методов элемента DOM элемента, который предоставляется через forwardRef родительскому компоненту.