5 кастомных React хуков, которые улучшат ваш код
2 года назад·3 мин. на чтение
В этой статье рассмотрим несколько очень полезных React хуков.
1. Хук useWindowSize
- хук для получения размера экрана
Я уверен, что в некоторых проектах, над которыми вы работали, вам нужно было получить ширину и высоту окна пользователя.
Так вот, теперь у вас есть хук для этого, так что вы можете сделать это еще проще, чем раньше.
Этот хук может быть особенно полезен при реализации отзывчивого дизайна, когда по какой-то причине вам нужно запустить определенный код при определенных размерах. Более продвинутый вариант этого хука можно найти в статье “Хук useResize для отслеживания ширины экрана в ReactJS”.import { useState, useEffect } from "react"; interface WindowSize { width: number; height: number; } const useWindowSize = (): WindowSize => { const [windowSize, setWindowSize] = useState<WindowSize>({ width: window.innerWidth, height: window.innerHeight, }); useEffect(() => { const handleResize = () => { setWindowSize({ width: window.innerWidth, height: window.innerHeight, }); }; window.addEventListener("resize", handleResize); return () => { window.removeEventListener("resize", handleResize); }; }, []); return windowSize; };
2️. Хук useKeyPress
- хук для определения нажатия клавиши
Следующий хук позволяет определить, когда нажата определенная клавиша. Это может вызвать события или действия, основанные на нажатой клавише. Например, для закрытия модального окна, отправки формы и т.д.
Пример использования:import { useState, useEffect } from "react"; const useKeyPress = (targetKey: string): boolean => { const [keyPressed, setKeyPressed] = useState(false); const downHandler = ({ key }: KeyboardEvent) => { if (key === targetKey) { setKeyPressed(true); } }; const upHandler = ({ key }: KeyboardEvent) => { if (key === targetKey) { setKeyPressed(false); } }; useEffect(() => { window.addEventListener("keydown", downHandler); window.addEventListener("keyup", upHandler); return () => { window.removeEventListener("keydown", downHandler); window.removeEventListener("keyup", upHandler); }; }, []); return keyPressed; };
const closeModalKeyPress = useKeyPress("Escape");
3. Хук useInterval
- хук для вызова функции setInterval
Этот хук позволяет вам использовать функцию setInterval
в качестве хука. Как и функция setInterval
, этот хук имеет множество применений, например, анимация, обновление данных через регулярные промежутки времени или даже установка таймера.
Можно использовать этот хук следующим образом:import { useState, useEffect, useRef } from "react"; const useInterval = (callback: () => void, delay: number | null) => { const savedCallback = useRef<() => void>(); useEffect(() => { savedCallback.current = callback; }, [callback]); useEffect(() => { function tick() { savedCallback.current && savedCallback.current(); } if (delay !== null && delay > 0) { let id = setInterval(tick, delay); return () => clearInterval(id); } else { tick(); } }, [delay]); };
const [count, setCount] = useState(0); useInterval(() => { setCount(count + 1); }, 1000);
4. Хук useDebounce
Теперь мы поговорим о хуке, который выполняет функцию только после того, как пройдет определенное количество времени без ее вызова.
Это полезно, например, для ограничения скорости вызовов API или обновления состояния при изменении ввода, например, когда вы набираете текст в поисковой строке.
Пример использования:import { useEffect, useRef } from 'react'; export function useDebounce(callback:Function, timeout: number = 200, deps: Array<any> = []) { const data = useRef({ firstTime: true }); useEffect(() => { const { firstTime, clearFunc } = data.current; const handler = setTimeout(() => { if (clearFunc && typeof clearFunc === 'function') { clearFunc(); } data.current.clearFunc = callback(); }, timeout); return () => { clearTimeout(handler); }; }, [timeout, ...deps]); } export default useDebounce;
const [inputValue, setInputValue] = useState(""); useDebounce(() => { // вызов APIl }, 500);
5️. Хук useThrottle
Throttle означает, что функция будет выполняться один раз за каждый заданный промежуток времени. Это может быть полезно для предотвращения быстрого запуска слишком большого количества вызовов API или событий.
Пример:import { useEffect, useRef } from 'react'; export const useThrottle = (callback:Function, delay: number = 200, deps: Array<any> = []) => { const lastRan = useRef(Date.now()); useEffect( () => { const handler = setTimeout(function() { if (Date.now() - lastRan.current >= delay) { callback(); lastRan.current = Date.now(); } }, delay - (Date.now() - lastRan.current)); return () => { clearTimeout(handler); }; }, [delay, ...deps], ); }; export default useThrottle;
Еще больше крутых хуков вы можете найти в каталоге хуков.const [inputValue, setInputValue] = useState(""); useThrottle(() => { // вызов API }, 500);
Что такое payload в Redux
год назад·1 мин. на чтение
Работая с Redux вы сталкивались с таким полем как `payload`, которое передается в action’е
Payload (пэйлоад, полезная нагрузка) — это неофициальное, принятое сообществом соглашение об именовании поля, которое содержит фактические данные в объекте действия (action) в Redux.
В официальной документации говорится только, что действие Redux должно быть простым объектом и должно иметь имя действия, представленное строкой:
Этот простой объект, который описывает изменение, которое применяется в нашем приложении. Действия должны иметь поле для типа (
type
), указывающее тип выполняемого действия. Типы могут быть определены как константы и импортированы из другого модуля. Лучше использовать строки для текста, чем символы, потому что строки сериализуются. Помимо типа, структура объекта действия зависит только от программиста.
Лучшие практики сообщества
Многие вещи не стандартизированы в Redux, поэтому у вас есть максимальная гибкость, чтобы делать все по-своему, но, поскольку большинство из нас не хотят придумывать индивидуальное решение для каждой мелочи повседневной детали, сообщество имеет тенденцию устанавливать лучшие практики. Чтобы отделить этот тип от обычных данных, используется свойствоpayload
. Теперь вопрос в том, что должно входить в эту полезную нагрузку (payload).
Необязательное свойство payload МОЖЕТ иметь значение любого типа. Он представляет собой полезную нагрузку действия (redux action). Любая информация о действии, которая не является type
или состоянием действия, должна быть частью поля payload
.
Например:
Это общепринятое соглашение о том, чтобы иметь тип и полезную нагрузку для действия. Полезной нагрузкой может быть любой допустимый тип JS (строка, массив, объект и т.д.). Узнать больше о Редакс можно здесь.const someAction = { type: "Test", payload: { user: "Test User", age: 25 }, }