Перейти к содержимому

10. Custom Hooks

Иллюстрация к уроку Custom Hooks позволяют нам извлекать логику компонента в переиспользуемые функции. Это мощный инструмент для организации и упрощения React-компонентов. Давайте разберемся, как их создавать и использовать.

Custom Hook - это JavaScript функция, имя которой начинается с use, и которая может использовать другие хуки React. Основная идея заключается в том, чтобы инкапсулировать логику, связанную с состоянием и побочными эффектами, и повторно использовать ее в разных компонентах.

Предположим, нам нужно реализовать счетчик в нескольких компонентах. Вместо того, чтобы дублировать логику, создадим useCounter hook:

import { useState } from 'react';
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => {
setCount(prevCount => prevCount + 1);
};
const decrement = () => {
setCount(prevCount => prevCount - 1);
};
const reset = () => {
setCount(initialValue);
};
return { count, increment, decrement, reset };
}
export default useCounter;

В этом примере:

  • Мы импортируем useState из react.
  • useCounter принимает начальное значение счетчика (initialValue).
  • Он возвращает объект с текущим значением count и функциями для изменения счетчика: increment, decrement и reset.

Теперь мы можем использовать этот hook в любом компоненте:

import React from 'react';
import useCounter from './useCounter';
function MyComponent() {
const { count, increment, decrement, reset } = useCounter(10); // Начальное значение 10
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
}
export default MyComponent;

Другой распространенный пример - хук для получения данных с сервера:

import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const json = await response.json();
setData(json);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]); // Зависимость от url, чтобы хук выполнялся при изменении url
return { data, loading, error };
}
export default useFetch;

Использование:

import React from 'react';
import useFetch from './useFetch';
function MyDataComponent() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
export default MyDataComponent;

Custom Hooks широко используются в библиотеках и фреймворках React. Например:

  • Redux Toolkit: Использует custom hooks (useDispatch, useSelector) для упрощения работы с Redux store.
  • React Router: Предоставляет useParams, useLocation, useHistory для доступа к информации о маршрутизации.
  • Formik/React Hook Form: Используют custom hooks для управления состоянием и валидацией форм.

Многие компании создают свои собственные библиотеки custom hooks для переиспользования логики между разными проектами. Например, хуки для работы с API, авторизацией, геолокацией и т.д.

  • Имена custom hooks должны начинаться с use.
  • Custom hooks могут использовать другие хуки (useState, useEffect, useContext и т.д.).
  • Custom hooks позволяют переиспользовать логику состояния и побочных эффектов.
  • Они улучшают читаемость и поддерживаемость кода.
  • Custom hooks не являются компонентами, они просто функции.