Сборник пользовательских хуков на React.js
Хук для взаимодействия с клавиатурой
import { useEffect } from 'react'
const useKeyListener = (callback) => {
useEffect(() => {
const listener = (e) => {
e = e || window.event
const tagName = e.target.localName || e.target.tagName
// Принимаем только события на уровне body,
// чтобы избежать их перехвата, например, в полях ввода
if (tagName.toUpperCase() === 'BODY') {
callback(e)
}
}
document.addEventListener('keydown', listener, true)
return () => {
document.removeEventListener('keydown', listener, true)
}
}, [callback])
}
export default useKeyListener
Хук для склонения слов
Хук, который в зависимости от числа подставляет необходимое склонение слова или выражения.
Пример использования:
const { text } = useWordDeclination(correctAnswersCount, [
"верный ответ",
"верных ответа",
"верных ответов",
])
Реализация (TypeScript):
import { useMemo } from "react"
export const useWordDeclination = (
n: number,
strings: [string, string, string],
) => {
const text = useMemo(() => {
const words = [strings[0], strings[1], strings[2]]
return words[
n % 100 > 4 && n % 100 < 20
? 2
: [2, 0, 1, 1, 1, 2][n % 10 < 5 ? n % 10 : 5]
]
}, [n, strings])
return { text }
}
Хук для изменения мета-тегов
Хук, изменяющий title и description мета-тэги для страницы при её открытии и восстанавливающий их значения при ее покидании.
Пример использования:
usePageMeta({ title, description })
Реализация:
import { useEffect } from "react"
type Props = {
title: string
description?: string
}
const DEFAULT = {
title: "Заголовок страницы по умолчанию (заголовок для главной страницы)",
description: "Описание по умолчанию (описание для главной страницы)",
}
export const usePageMeta = ({ title, description }: Props) => {
useEffect(() => {
document.title = title
description &&
document
.querySelector('head meta[name="description"]')
?.setAttribute("content", description)
return () => {
document.title = DEFAULT.title
document
.querySelector('head meta[name="description"]')
?.setAttribute("content", DEFAULT.description)
}
}, [title, description])
}
Хук для управления модальным окном
export function useModal() {
const [isOpened, setIsOpened] = useState(false);
const restrictBodyScroll = () => {
document.body.style.height = "100vh";
document.body.style.overflow = "hidden";
};
const allowBodyScroll = () => {
document.body.style.height = "";
document.body.style.overflow = "";
};
const open = () => {
setTimeout(() => {
restrictBodyScroll();
}, 0);
setIsOpened(true);
};
const close = () => {
allowBodyScroll();
setIsOpened(false);
};
useEffect(() => {
return close;
}, []);
return {
isOpened,
open,
close,
};
}
setTimeout
в open
нужен для того, чтобы скролл body
корректно запретился в том случае, если модалка открывается сразу после закрытия предыдущей.
Пример использования:
const SomeComponent = () => {
const confirmModal = useModal();
return (
<div>
<button onClick={confirmModal.open}>Открыть модальное окно</button>
<SomeModalComponent
isOpened={confirmModal.isOpened}
close={confirmModal.close}
/>
</div>
);
};
export default SomeComponent;
Хук для получения размеров окна
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;
};
Хук для 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]);
};
Хук для доступа к предыдущему значению стейта
import { useRef, useEffect } from "react";
const usePrevious = <T>(value: T): T | undefined => {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
export default usePrevious;
Пример использования:
import React, { useState } from "react";
import usePrevious from "./usePrevious";
const Counter = () => {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
const handleClick = () => {
setCount(count => count + 1);
};
return (
<div>
Current count: {count}, Previous count: {prevCount}
<button onClick={handleClick}>Increment</button>
</div>
);
};
export default Counter;
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для троттлинга выполнения
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для отложенного выполнения
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для работы с Intersection Observer
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для получения информации о сетевом соединении
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для информации о геолокации в реальном времени
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для преобразования голоса в текст
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для продвинутых жестов на тачпадах
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для отслеживания выделения текста
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для взаимодействия между вкладками
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для работы с Cookie
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для отслеживания размеров элемента
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для работы с localStorage
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для отслеживания активности пользователя
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для отслеживания долгого нажатия
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для копирования в буффер обмена
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для динамической высоты textarea
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Хук для работы с Web Share API
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=32&q=75)
Также в этой категории
Вам может быть интересно
Топ тредов
: Предложите идею и получите спонсорский доступ на месяц
: Можно добавить таймер на решение задач
: Добавьте angular раздел
![Логотип Девстанции Логотип Девстанции](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.767d6ec0.png&w=48&q=75)