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
родительскому компоненту.