API хуков React стал эволюционным скачком в том, как мы обрабатываем состояние и побочные эффекты в наших компонентах React. Хуки позволяют использовать состояние и другие функции React без написания класса. Среди всего разнообразия хуков выделяется одна особенность — возможность создавать свои собственные хуки. Это позволяет вам абстрагировать и повторно использовать логику состояния в компонентах, делая ваш код СУХИМ (не повторяйте себя), более легким для чтения и более удобным для сопровождения. В этом посте мы углубимся в мир кастомных хуков.
Разрушение пользовательских хуков
Пользовательские хуки — это, по сути, функции JavaScript, которые начинаются с префикса «использовать». Пользовательский хук может содержать вызовы других хуков, таких как useState
или useEffect
, создавая повторно используемый фрагмент логики, который можно использовать между различными компонентами.
Чтобы лучше понять пользовательские хуки, давайте сначала вернемся к стандартным хукам, которые предоставляет React.
Основные хуки: строительные блоки пользовательских хуков
Прежде чем мы углубимся в создание пользовательских хуков, стоит кратко рассказать об основных хуках, предоставляемых React, поскольку они будут служить нашими строительными блоками.
использование состояния
useState
— это хук, который мы используем для добавления состояния нашим функциональным компонентам. Вот простой пример использования:
import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
использованиеЭффект
useEffect
— это хук, который позволяет нам выполнять побочные эффекты в наших функциональных компонентах. Среди прочего, побочными эффектами могут быть выборка данных, подписки или ручное изменение DOM. Вот простой пример useEffect
:
import { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
В этом примере хук useEffect
обновляет заголовок документа после того, как React обновляет DOM.
Создание нашего первого пользовательского крючка
Повторив хуки useState и useEffect, давайте теперь приступим к созданию нашего собственного пользовательского хука. Для нашего первого примера мы создадим хук, который отслеживает текущий размер окна.
import { useState, useEffect } from 'react'; function useWindowSize() { // We initialize the state with undefined to distinguish between the // JavaScript environment and when we've measured the window size. const [windowSize, setWindowSize] = useState({ width: undefined, height: undefined, }); useEffect(() => { // We define a function to call when the window is resized. function handleResize() { // We set the window width and height into the state. setWindowSize({ width: window.innerWidth, height: window.innerHeight, }); } // We add an event listener to the window for the resize event. window.addEventListener("resize", handleResize); // We call the handleResize function to set the initial size. handleResize(); // Cleanup after effect // We remove the event listener when the component is unmounted. return () => window.removeEventListener("resize", handleResize); }, []); // The empty array ensures that this effect runs only on component mount return windowSize; }
В этом фрагменте кода мы создаем хук useWindowSize
, который использует хуки useState
и useEffect
для отслеживания текущего размера окна.
Использование нашего пользовательского хука
Теперь, когда мы создали наш пользовательский хук, давайте посмотрим, как мы можем использовать его в компоненте:
import React from 'react'; import useWindowSize from './useWindowSize'; function ShowWindowDimensions() { const size = useWindowSize(); return ( <div> {size.width}px / {size.height}px </div> ); } export default ShowWindowDimensions;
Здесь мы используем наш хук useWindowSize
в компоненте ShowWindowDimensions
. Этот компонент теперь будет отображать текущую ширину и высоту окна и будет перерисовываться при каждом изменении размера окна.
Шаг вперед: пример более сложного пользовательского хука
Давайте рассмотрим более сложный пример, в котором мы создаем собственный хук для получения данных из API.
import { useState, useEffect } from 'react'; function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { async function fetchData() { setLoading(true); try { const response = await fetch(url); const data = await response.json(); setData(data); setError(null); } catch (error) { setError(error); } finally { setLoading(false); } } fetchData(); }, [url]); // dependency array ensures the effect runs when url changes return { data, loading, error }; }
В хуке useFetch
мы используем useState
для управления данными, загрузкой и состояниями ошибок. Хук useEffect
отвечает за получение данных с предоставленного URL-адреса.
Использование пользовательского хука выборки данных
Чтобы использовать наш хук useFetch
, мы создаем компонент, который извлекает и отображает список сообщений из JSONPlaceholder:
import React from 'react'; import useFetch from './useFetch'; function Posts() { const { data: posts, loading, error } = useFetch("https://jsonplaceholder.typicode.com/posts"); if (loading) { return <div>Loading...</div>; } if (error) { return <div>Error: {error.message}</div>; } return ( <div> <h1>Posts</h1> {posts.map((post) => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.body}</p> </div> ))} </div> ); } export default Posts;
Здесь компонент Posts
извлекает и отображает список сообщений. Состояние компонента (данные, загрузка и ошибка) полностью управляется хуком useFetch
.
Заключение: сила нестандартных хуков
Пользовательские хуки предлагают мощный способ извлечения логики компонентов в многократно используемые функции. Они помогают уменьшить дублирование кода и упрощают его чтение и поддержку. Кроме того, они поощряют хорошую архитектуру, способствуя разделению задач внутри ваших компонентов. Каждый пользовательский хук инкапсулирует свое собственное состояние и побочные эффекты, что приводит к более модульному и понятному коду.
По словам инженера-программиста Роберта К. Мартина, «Чистый код не создается с соблюдением набора правил. Вы не станете мастером программного обеспечения, изучив список эвристик. Профессионализм и мастерство исходят из ценностей, которые определяют дисциплину». Используя настраиваемые хуки для абстрагирования и повторного использования логики в компонентах, мы можем создавать более профессиональный, удобный в сопровождении и чистый код.
Помните, что React — это создание повторно используемых компонентов, и пользовательские хуки позволяют вам применять этот принцип даже к вашей логике и побочным эффектам. Приведенные здесь примеры — лишь верхушка айсберга. С нестандартными крючками ваши возможности безграничны. Удачного кодирования!
Этот комплексный подход должен обеспечить четкое понимание пользовательских хуков, от их создания до их использования. Эта концепция является мощной, поскольку она обеспечивает надежный и модульный подход к структурированию проектов React, упрощая масштабирование и поддержку приложений с течением времени. Пользовательские хуки, как и встроенные хуки, обеспечивают огромную мощность, гибкость и возможность повторного использования функциональных компонентов, что делает их обязательными для любого современного разработчика React.
Если вам понравилась статья и вы хотите выразить свою поддержку, сделайте следующее:
👏 Аплодируйте истории (50 аплодисментов), чтобы эта статья попала в топ
👉Подпишитесь на меня в Среднем
Посмотрите больше контента в моем профиле Medium