Кастомные хуки в react
- вторник, 11 марта 2025 г. в 00:00:06
React хуки произвели революцию в том, как мы пишем компоненты, особенно новые хуки из 19 версии для форм. Но помимо встроенных хуков, мы можем создавать собственные, чтобы переиспользовать логику между компонентами. Давайте разберемся, как это делать.
Кастомный хук - это обычная функция, название которой начинается с "use", и которая может вызывать другие хуки. Рассмотрим простой пример
const useBoolean = (initialValue = false) => {
const [value, setValue] = useState(initialValue);
const toggle = (value?: boolean) => setValue((prev) => value ?? !prev);
return [value, toggle];
};
Этот хук управляет булевым состоянием и предоставляет функцию для его переключения. Использование очень простое:
function Component() {
const [isOpen, toggle] = useBoolean(false);
return (
<button onClick={() => toggle()}>
{isOpen ? 'Закрыть' : 'Открыть'}
</button>
);
}
Единая ответственность: каждый хук должен решать одну конкретную задачу
Переиспользуемость: хук должен быть достаточно абстрактным для использования в разных ситуациях
Понятный интерфейс: возвращаемые значения и методы должны иметь очевидные названия
Часто в React-приложениях можно встретить такую реализацию
Часто в React-приложениях или готовых пакетах можно встретить такую реализацию:
const useIsClient = () => {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return isClient;
};
На первый взгляд, это обычный хук, который определяет, выполняется ли код на клиенте. Однако, давайте разберем, почему такой подход не оптимален:
Лишний рендер: При первом рендере isClient всегда будет false, а затем произойдет повторный рендер со значением true. Это приводит к ненужной работе.
Несоответствие SSR/CSR: Во время серверного рендеринга значение всегда будет false, что может привести к проблемам гидратации.
Избыточность: В современном React есть более простое решение:
const isClient = typeof window !== 'undefined';
Это не хук, а простая константа, которая:
Определяется один раз при импорте модуля
Не вызывает повторных рендеров
Корректно работает как на сервере, так и на клиенте
Этот пример хорошо иллюстрирует важный принцип: не все решения в React должны быть хуками. Иногда простая утилитарная функция или константа может быть более эффективным решением.
Хотя создавать собственные хуки очень полезно для понимания их работы, часто нет необходимости "изобретать велосипед". Существуют готовые библиотеки с большим набором оптимизированных хуков.
Одно из таких решений - @siberiacancode/reactuse. Эта библиотека предоставляет множество готовых хуков для различных задач:
Управление состоянием
Работа с DOM
Датчики и события
Анимации
Сетевые запросы
И многое другое
🚀 Более 100 готовых хуков
📦 Небольшой размер благодаря tree-shaking
💪 Полная типизация TypeScript
📝 Подробная документация
⚡ Высокая производительность
🔧 Простота использования
import { useBoolean, useLocalStorage, useWindowSize } from '@siberiacancode/reactuse';
function App() {
const [isOpen, toggle] = useBoolean(false);
const [user, setUser] = useLocalStorage('user', null);
const { width, height } = useWindowSize();
// ...
}
Создание собственных хуков - это мощный инструмент для переиспользования логики в React-приложениях. Однако для продакшн-проектов рекомендуется использовать проверенные решения вроде @siberiacancode/reactuse, которые предоставляют оптимизированные и хорошо протестированные реализации часто используемых хуков.
Начните с изучения создания простых хуков, чтобы понять принципы их работы, но не стесняйтесь использовать готовые решения для ускорения разработки и улучшения качества кода.