Главная » Статьи » Как создать свой первый React Hook от начала до конца

Как создать свой первый React Hook от начала до конца

Как создать свой первый React Hook от начала до конца

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

Какую функцию мы хотим добавить?

На моем веб-сайте reedbarger.com я разрешаю пользователям копировать код из моих статей с помощью пакета под названием react-copy-to-clipboard.

Пользователь просто наводит курсор на фрагмент, нажимает кнопку буфера обмена, и код добавляется в буфер обмена его компьютера. Это позволяет потом вставлять и использовать код где угодно.

Как создать свой первый React Hook от начала до конца

Как создать react-copy-to-clipboard

Вместо того, чтобы использовать стороннюю библиотеку, я хотел создать эту функциональность с помощью собственного React hook.

Как и каждый пользовательский React hooks, созданый мною, я помещаю его в отдельную папку, обычно называемую utils или lib, специально для функций, которые я могу повторно использовать в приложении.

Поместим наш hook в файл с именем useCopyToClipboard.js и создадим функцию с таким же именем. Также не забудьте импортировать React вверху.

Есть несколько способов скопировать текст в буфер обмена пользователя. Однако я предпочитаю использовать для этого библиотеку, которая делает процесс более надежным, называемую copy-to-clipboard. Она экспортирует функцию copy, которую мы будем вызывать.

// utils/useCopyToClipboard.js
import React from "react";
import copy from "copy-to-clipboard"; export default function useCopyToClipboard() {}

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

Как сделать функцию handleCopy

Внутри функции нам сначала нужно убедиться, что она принимает только данные строкового или числового типа. Мы используем if-else, который будет проверять, является ли тип строкой или числом. В противном случае — будем регистрировать ошибку в консоли, которая сообщает пользователю, что он не может копировать другие типы.

import React from "react";
import copy from "copy-to-clipboard"; export default function useCopyToClipboard() { const [isCopied, setCopied] = React.useState(false); function handleCopy(text) { if (typeof text === "string" || typeof text == "number") { // copy } else { // don't copy console.error( `Cannot copy typeof ${typeof text} to clipboard, must be a string or number.` ); } }
}

Затем нам нужно взять текст и преобразовать его в строку, которую мы затем передадим функции copy. Оттуда мы хотим вернуть функцию копирования дескрипторов из нашего хука. Как правило, функция handleCopy будет связана с одной из кнопок onClick.

import React from "react";
import copy from "copy-to-clipboard"; export default function useCopyToClipboard() { function handleCopy(text) { if (typeof text === "string" || typeof text == "number") { copy(text.toString()); } else { console.error( `Cannot copy typeof ${typeof text} to clipboard, must be a string or number.` ); } } return handleCopy;
}

Кроме того, нам нужно некоторое состояние, которое показывает, был ли текст скопирован или нет. Чтобы создать его, мы вызовем useState в верхней части хука и создадим новую переменную состояния isCopied, в которой будет вызываться сеттер setCopy.

Изначально это значение будет false. Если текст успешно скопирован, мы установим значение true. В противном случае оно останется false. Наконец, мы вернем isCopied из хука в массиве вместе с handleCopy.

import React from "react";
import copy from "copy-to-clipboard"; export default function useCopyToClipboard(resetInterval = null) { const [isCopied, setCopied] = React.useState(false); function handleCopy(text) { if (typeof text === "string" || typeof text == "number") { copy(text.toString()); setCopied(true); } else { setCopied(false); console.error( `Cannot copy typeof ${typeof text} to clipboard, must be a string or number.` ); } } return [isCopied, handleCopy];
}

Как использовать useCopyToClipboard

Теперь мы можем применить useCopyToClipboard к любому компоненту. В моем случае я буду использовать его с компонентом кнопки копирования, который получил фрагмента кода.

Все, что нам нужно сделать, чтобы это работало — кликнуть по кнопке. И при возврате функции, называемой копией дескриптора, получим запрошенный код в виде текста. И как только текст скопирован — isCopied изменит значение на true. Мы можем показать другой значок, указывающий, что копия была успешной.

import React from "react";
import ClipboardIcon from "../svg/ClipboardIcon";
import SuccessIcon from "../svg/SuccessIcon";
import useCopyToClipboard from "../utils/useCopyToClipboard"; function CopyButton({ code }) { const [isCopied, handleCopy] = useCopyToClipboard(); return ( <button onClick={() => handleCopy(code)}> {isCopied ? <SuccessIcon /> : <ClipboardIcon />} </button> );
}

Как добавить интервал сброса

Есть одно улучшение, которое мы можем внести в наш код. Как мы уже писали, наш хук isCopied всегда будет истинным, что означает, что мы всегда будем видеть иконку успеха:

Как создать свой первый React Hook от начала до конца

Если мы хотим сбросить состояние через несколько секунд, мы можем передать временной интервал для useCopyToClipboard. Давайте добавим этот функционал.

Вернувшись к нашему хуку, мы можем создать параметр с именем resetInterval, значение которого по умолчанию равно null, что гарантирует, что состояние не будет сброшено, если ему не будет передан аргумент.

Затем мы добавим, useEffect чтобы сказать, что если текст скопирован и у нас есть интервал сброса, мы вернем isCopied значение false после этого интервала, используя setTimeout. Кроме того, нам нужно очистить этот тайм-аут.

import React from "react";
import copy from "copy-to-clipboard"; export default function useCopyToClipboard(resetInterval = null) { const [isCopied, setCopied] = React.useState(false); const handleCopy = React.useCallback((text) => { if (typeof text === "string" || typeof text == "number") { copy(text.toString()); setCopied(true); } else { setCopied(false); console.error( `Cannot copy typeof ${typeof text} to clipboard, must be a string or number.` ); } }, []); React.useEffect(() => { let timeout; if (isCopied && resetInterval) { timeout = setTimeout(() => setCopied(false), resetInterval); } return () => { clearTimeout(timeout); }; }, [isCopied, resetInterval]); return [isCopied, handleCopy];
}

И, наконец, мы можем сделать последнее усовершенствование — обернуть handleCopy в useCallback для того , чтобы убедиться, что он не будет воссоздан при каждом повторном вызове.

Конечный результат

Теперь у нас есть хук, который позволяет сбрасывать состояние через заданный интервал времени. Вот что мы должны увидеть в результате:

import React from "react";
import ClipboardIcon from "../svg/ClipboardIcon";
import SuccessIcon from "../svg/SuccessIcon";
import useCopyToClipboard from "../utils/useCopyToClipboard"; function CopyButton({ code }) { // isCopied is reset after 3 second timeout const [isCopied, handleCopy] = useCopyToClipboard(3000); return ( <button onClick={() => handleCopy(code)}> {isCopied ? <SuccessIcon /> : <ClipboardIcon />} </button> );
}

Как создать свой первый React Hook от начала до конца

Я надеюсь, что вы узнали кое-что новое в процессе создания нашего хука и что вы будете использовать его в своих проектах для копирования любого текста в буфер обмена.

Автор: Reed Barger

Источник: www.freecodecamp.org

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен