Русский
Русский
English
Статистика
Реклама

Перевод 5 React-хуков, которые пригодятся в любом проекте

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



Хук useModalState


Модальные окна широко используются в веб-приложениях, они применяются в самых разных ситуациях. При работе с подобными окнами быстро приходит понимание того, что управление их состоянием это трудоёмкая задача, решая которую, приходится постоянно выполнять одни и те же рутинные действия. А если имеется код, написание которого отнимает немало сил и времени, код, который приходится постоянно повторять в разных местах приложения, это значит, что такой код имеет смысл абстрагировать, оформив в виде самостоятельной сущности. Хук useModalState это именно такой код, используемый для управления состоянием модальных окон.

Собственные версии этого хука предоставляют многие библиотеки. Одна из них это Chakra UI. Если вас интересуют подробности об этой библиотеке вот мой материал о ней.

Реализация useModalState весьма проста, даже тривиальна. Но опыт подсказывает мне, что гораздо лучше пользоваться им, чем постоянно заново писать код для управления состоянием модальных окон.

Вот код этого хука:

import React from "react";import Modal from "./Modal";export const useModalState = ({ initialOpen = false } = {}) => {const [isOpen, setIsOpen] = useState(initialOpen);const onOpen = () => {setIsOpen(true);};const onClose = () => {setIsOpen(false);};const onToggle = () => {setIsOpen(!isOpen);};return { onOpen, onClose, isOpen, onToggle };};

А вот пример его использования:

const Client = () => {const { isOpen, onToggle } = useModalState();const handleClick = () => {onToggle();};return (<div><button onClick={handleClick} /><Modal open={isOpen} /></div>);};export default Client;

Хук useConfirmationDialog


Хук useConfirmationDialog тоже имеет отношение к модальным окнам. И им я тоже пользуюсь довольно часто. Если пользователь некоего приложения выполняет какие-то важные действия, вроде удаления чего-либо, у него принято запрашивать подтверждение выполнения подобных действий. Поэтому такую логику имеет смысл абстрагировать в виде хука. Вот один из вариантов реализации хука useConfirmationDialog:

import React, { useCallback, useState } from 'react';import ConfirmationDialog from 'components/global/ConfirmationDialog';export default function useConfirmationDialog({headerText,bodyText,confirmationButtonText,onConfirmClick,}) {const [isOpen, setIsOpen] = useState(false);const onOpen = () => {setIsOpen(true);};const Dialog = useCallback(() => (<ConfirmationDialogheaderText={headerText}bodyText={bodyText}isOpen={isOpen}onConfirmClick={onConfirmClick}onCancelClick={() => setIsOpen(false)}confirmationButtonText={confirmationButtonText}/>),[isOpen]);return {Dialog,onOpen,};}

Вот пример его использования:

import React from "react";import { useConfirmationDialog } from './useConfirmationDialog'function Client() {const { Dialog, onOpen } = useConfirmationDialog({headerText: "Delete this record?",bodyText:"Are you sure you want delete this record? This cannot be undone.",confirmationButtonText: "Delete",onConfirmClick: handleDeleteConfirm,});function handleDeleteConfirm() {//TODO: удалить}const handleDeleteClick = () => {onOpen();};return (<div><Dialog /><button onClick={handleDeleteClick} /></div>);}export default Client;

Тут стоит обратить внимание на то, что эта реализация useConfirmationDialog нормально работает до тех пор, пока в модальном окне подтверждения операции нет управляемых элементов, представленных полями для ввода данных. Если в вашем окне такие элементы имеются лучше создать для такого модального окна отдельный компонент. Дело тут в том, что вам вряд ли понравится то, что содержимое модального окна, включая и такие поля, будет повторно рендериться каждый раз, когда пользователь вводит в поля какие-то данные.

Хук useAsync


Грамотная поддержка асинхронных операций в приложении это задача, решить которую сложнее, чем кажется на первый взгляд. Так, может иметься множество переменных, хранящихся в состоянии, за которыми нужно наблюдать в процессе выполнения подобных операций. Приложение может сообщать пользователю о ходе выполнения асинхронной операции, показывая ему индикатор прогресса. Кроме того, нужно обрабатывать ошибки асинхронных операций и, если они происходят, выдавать адекватные сообщения о них. В результате наличие в React-проекте хорошо проработанного фреймворка, обеспечивающего поддержку асинхронных операций, окупится сторицей. Хук useAsync может оказаться полезным именно для решения вышеописанных задач. Вот его код:

export const useAsync = ({ asyncFunction }) => {const [loading, setLoading] = useState(false);const [error, setError] = useState(null);const [result, setResult] = useState(null);const execute = useCallback(async (...params) => {try {setLoading(true);const response = await asyncFunction(...params);setResult(response);} catch (e) {setError(e);}setLoading(false);},[asyncFunction]);return { error, result, loading, execute };};

А ниже показан пример его использования:

import React from "react";export default function Client() {const { loading, result, error, execute } = useAsync({asyncFunction: someAsyncTask,});async function someAsyncTask() {// выполнение асинхронной операции}const handleClick = () => {execute();};return (<div>{loading && <p>loading</p>}{!loading && result && <p>{result}</p>}{!loading && error?.message && <p>{error?.message}</p>}<button onClick={handleClick} /></div>);}

Такой хук несложно написать самостоятельно. Я часто поступаю именно так. Но вам, возможно, имеет смысл присмотреться к более зрелой библиотечной реализации подобного механизма. Например к этой.

Хук useTrackErrors


Валидация форм это ещё одна задача, решаемая в рамках React-приложений, которую программисты находят достаточно скучной. Учитывая это, можно отметить, что существует множество отличных библиотек, помогающих управлять формами в React-проектах. Одна из них это formik. Но прежде чем эффективно пользоваться любой библиотекой, нужно потратить некоторое время на её изучение. Часто это приводит к тому, что в маленьких проектах подобные библиотеки использовать просто бессмысленно. В особенности если над проектом работает команда разработчиков, не все из которых знакомы с некоей библиотекой.

Но это не значит, что у нас не может быть простых абстракций, представляющих какие-то фрагменты кода, которым мы пользуемся достаточно часто. Один из таких фрагментов кода, который я обычно оформляю в виде самостоятельной сущности, связан с проверкой форм на наличие в них ошибок. Вот реализация простого хука useTrackErrors, способного помочь в решении этой задачи:

import React, { useState } from "react";import FormControl from "./FormControl";import Input from "./Input";import onSignup from "./SignupAPI";export const useTrackErrors = () => {const [errors, setErrors] = useState({});const setErrors = (errsArray) => {const newErrors = { ...errors };errsArray.forEach(({ key, value }) => {newErrors[key] = value;});setErrors(newErrors);};const clearErrors = () => {setErrors({});};return { errors, setErrors, clearErrors };};

Вот как можно пользоваться этим хуком:

import React, { useState } from "react";import FormControl from "./FormControl";import Input from "./Input";import onSignup from "./SignupAPI";export default function Client() {const { errors, setErrors, clearErrors } = useTrackErrors();const [name, setName] = useState("");const [email, setEmail] = useState("");const handleSignupClick = () => {let invalid = false;const errs = [];if (!name) {errs.push({ key: "name", value: true });invalid = true;}if (!email) {errs.push({ key: "email", value: true });invalid = true;}if (invalid) {setErrors(errs);return;}onSignup(name, email);clearErrors();};const handleNameChange = (e) => {setName(e.target.value);setErrors([{ key: "name", value: false }]);};const handleEmailChange = (e) => {setEmail(e.target.value);setErrors([{ key: "email", value: false }]);};return (<div><FormControl isInvalid={errors["name"]}><FormLabel>Full Name</FormLabel><InputonKeyDown={handleKeyDown}onChange={handleNameChange}value={name}placeholder="Your name..."/></FormControl><FormControl isInvalid={errors["email"]}><FormLabel>Email</FormLabel><InputonKeyDown={handleKeyDown}onChange={handleEmailChange}value={email}placeholder="Your email..."/></FormControl><button onClick={handleSignupClick}>Sign Up</button></div>);}

Хук useDebounce


То, что называется debouncing, способно найти применение в любом приложении. В частности, речь идёт об уменьшении частоты выполнения ресурсоёмких операций. Например, это предотвращение вызова API поиска данных после каждого нажатия на клавишу в ходе ввода пользователем поискового запроса. Обращение к API будет выполнено после того, как пользователь завершит ввод данных. Хук useDebounce упрощает решение подобных задач. Вот его простая реализация, которая основана на AwesomeDebounceLibrary:

import AwesomeDebouncePromise from "awesome-debounce-promise";const debounceAction = (actionFunc, delay) =>AwesomeDebouncePromise(actionFunc, delay);function useDebounce(func, delay) {const debouncedFunction = useMemo(() => debounceAction(func, delay), [delay,func,]);return debouncedFunction;}

Вот практический пример использования этого хука:

import React from "react";const callAPI = async (value) => {// вызов дорогого API};export default function Client() {const debouncedAPICall = useDebounce(callAPI, 500);const handleInputChange = async (e) => {debouncedAPICall(e.target.value);};return (<form><input type="text" onChange={handleInputChange} /></form>);}

Используя этот хук стоит учитывать одну вещь: надо проконтролировать, чтобы дорогая функция не пересоздавалась бы при каждом рендеринге компонента. Дело в том, что это приведёт к сбросу замедленной версии этой функции и сотрёт всё из её внутреннего состояния. Обеспечить вышеописанное требование можно двумя путями:

  1. Можно объявить дорогую функцию за пределами функционального компонента (так, как сделано в примере).
  2. Можно обернуть такую функцию с помощью хука useCallback.

Итоги


Существует немало хороших библиотек, в которых реализованы самые разные хуки. Если вас интересуют подобные библиотеки можете начать знакомство с ними отсюда. Но, хотя в нашем распоряжении имеется множество полезных пользовательских хуков, хочу отметить, что те пять, о которых я рассказал это те самые хуки, которые пригодятся в любом React-проекте.

Какими React-хуками вы пользуетесь чаще всего?

Источник: habr.com
К списку статей
Опубликовано: 02.05.2021 12:15:03
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании ruvds.com

Разработка веб-сайтов

Javascript

Reactjs

React

Разработка

Ruvds_перевод

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru