Сборник пользовательских хуков на React.js
1. Хук для взаимодействия с клавиатурой
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
2. Хук для склонения слов
Хук, который в зависимости от числа подставляет необходимое склонение слова или выражения.
Пример использования:
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 }
}
3. Хук для изменения мета-тегов
Хук, изменяющий 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])
}
4. Хук для управления модальным окном
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;