Основная причина написания собственного хука — возможность повторного использования кода. Например, вместо того, чтобы писать один и тот же код для нескольких компонентов, использующих одну и ту же общую логику состояния (скажем, логику «setState» или localStorage), вы можете поместить этот код в пользовательский хук и повторно использовать его. Я покажу вам, как реализовать несколько полезных пользовательских хуков.
использоватьПредыдущий
Часто возникает вопрос: «При использовании хуков, как мне получить предыдущее значение свойства или состояния?». С компонентами класса React у вас есть метод componentDidUpdate, который получает предыдущие реквизиты и состояние в качестве аргументов, или вы можете обновить переменную экземпляра (this.previous = value) и ссылаться на нее позже, чтобы получить предыдущее значение. Итак, как мы можем сделать это внутри функционального компонента, у которого нет методов жизненного цикла или экземпляра для хранения значений? Крючки в помощь! Мы можем создать собственный хук, который использует внутренний хук useRef для хранения предыдущего значения. Смотрите рецепт ниже со встроенными комментариями.
import { useRef, useEffect } from "react"; export function usePrevious<T>(value: T): T | undefined { /* The ref object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class */ const ref = useRef(); // Store current value in ref useEffect(() => { ref.current = value; }, [value]); // Only re-run if value changes // Return previous value (happens before update in useEffect above) return ref.current; } // Ref: https://usehooks.com/usePrevious/
Использование
import React, { useState } from "react"; const prices = [100, 200, 300, 400, 500, 600, 700]; const Price = ({ price }) => { const prevPrice = usePrevious(price); const icon = prevPrice && prevPrice < price ? '😡' : '😊'; return ( <div> Current price: {price}; <br /> Previous price: {prevPrice} {icon} </div> ); }; const Page = () => { const [price, setPrice] = useState(100); const onPriceChange = (e) => setPrice(Number(e.target.value)); return ( <> <select value={price} onChange={onPriceChange}> {prices.map((price) => (<option value={price}>{price}$</option>))} </select> <Price price={price} /> </> ); }
использоватьTimeOut
Хук, чтобы легко использовать setTimeout(callback, delay)
, и он должен:
- Сбросьте таймер, если задержка изменится.
- НЕ сбрасывайте таймер, если изменяется только обратный вызов.
export function useTimeout(callback: () => void, delay: number) { const callbackFn = React.useRef(null) callbackFn.current = callback React.useEffect(() => { const timeoutId = setTimeout(() => { if (callbackFn.current) { callbackFn.current() } }, delay) return () => { clearTimeout(timeoutId) } }, [delay]) // Only re-run if delay changes }
Использование
import { useState } from 'react' export default function Component() { const [visible, setVisible] = useState(true) const hide = () => setVisible(false) useTimeout(hide, 5000) return ( <div> <p> {visible ? "I'm visible for 5000ms" : 'You can no longer see this content'} </p> </div> ) }
Рекомендации
Другие статьи
https://medium.com/@lama.ibrahim96/в чем разница между ключами-в-и-объектами-6d872a3d526a
Спасибо за прочтение. Если вы узнали что-то новое из этой статьи, подпишитесь на меня 😊 Я буду публиковать больше материалов о React и Javascript.