☕ 15 кастомных хуков для облегчения компонентов React

Появившиеся в React 16.8 хуки позволяют использовать состояние и прочие возможности библиотеки без написания классов. В небольшом обзоре приводятся 15 наиболее полезных из них.

Перевод публикуется с сокращениями, автор оригинальной статьи Nilanth.

React hooks – это модное в сообществе слово. Скорее всего каждый разработчик React знает, что такое хуки.

Кастомные хуки позволяют извлекать логику компонентов в повторно используемую функцию, что повышает разделение компонентов и надежность. Приступим к рассмотрению пятнадцати React hooks, которые сделают ваш компонент легковесным.

1. useIdle

С помощью useIdle можно отслеживать, находится ли пользователь на странице в режиме ожидания. Можете передать два параметра: ms – время ожидания и initialState, который позволяет пользователю изначально установить режим ожидания.

import {useIdle} from 'react-use';
const Demo = () => {
  const isIdle = useIdle(3e3);
return (
    <div>
      <div>User is idle: {isIdle ? 'Yes' : 'Nope'}</div>
    </div>
  );
};

2. useInterval

Этот хук можно использовать для функций с интервалами, которые автоматически размонтируют компонент clearInterval. Он также позволяет приостановить интервал, установив задержку равной нулю.

import * as React from 'react';
import {useInterval} from 'react-use';
const Demo = () => {
  const [count, setCount] = React.useState(0);
  const [delay, setDelay] = React.useState(1000);
  const [isRunning, toggleIsRunning] = useBoolean(true);
useInterval(
    () => {
      setCount(count + 1);
    },
    isRunning ? delay : null
  );
return (
    <div>
      <div>
        delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
      </div>
      <h1>count: {count}</h1>
      <div>
        <button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
      </div>
    </div>
  );
};

3. useScroll

Используется для прослушивания события прокрутки элемента и перерисовки при прокрутке. Не требует ручного добавления слушателей событий JavaScript.

import {useScroll} from 'react-use';
const Demo = () => {
  const scrollRef = React.useRef(null);
  const {x, y} = useScroll(scrollRef);
return (
    <div ref={scrollRef}>
      <div>x: {x}</div>
      <div>y: {y}</div>
    </div>
  );
};

4. useToggle

С помощью useToggle можно переключаться между двумя состояниями: TRUE и FALSE. Такой подход уменьшает «ручную» логику.

import {useToggle} from 'react-use';
const Demo = () => {
  const [on, toggle] = useToggle(true);
return (
    <div>
      <div>{on ? 'ON' : 'OFF'}</div>
      <button onClick={toggle}>Toggle</button>
      <button onClick={() => toggle(true)}>set ON</button>
      <button onClick={() => toggle(false)}>set OFF</button>
    </div>
  );
};

5. useTitle

Хук используется для установки заголовка страницы.

import {useTitle} from 'react-use';const Demo = () => {  useTitle('Hello world!');return null;};

6. usePrevious

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

import {usePrevious} from 'react-use';
const Demo = () => {
  const [count, setCount] = React.useState(0);
  const prevCount = usePrevious(count);
return (
    <p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      <p>
        Now: {count}, before: {prevCount}
      </p>
    </p>
  );
};

7. useSetState

Этот крючок используется для объединения объектов в их текущем состоянии, аналогично this.setState в компоненте класса. Если вы используете несколько состояний, их можно привести к одному с помощью useSetState.

import {useSetState} from 'react-use';
const Demo = () => {
  const [state, setState] = useSetState({});
return (
    <div>
      <pre>{JSON.stringify(state, null, 2)}</pre>
      <button onClick={() => setState({hello: 'world'})}>hello</button>
      <button onClick={() => setState({foo: 'bar'})}>foo</button>
      <button 
        onClick={() => {
          setState((prevState) => ({
            count: (prevState.count || 0) + 1,
          }))
        }}
      >
        count
      </button>
    </div>
  );
};

8. useCookie

Хук используется для возврата текущего значения cookie, обратного вызова обновления и удаления cookie.

import { useCookie } from "react-use";
const Demo = () => {
  const [value, updateCookie, deleteCookie] = useCookie("my-cookie");
  const [counter, setCounter] = useState(1);
useEffect(() => {
    deleteCookie();
  }, []);
const updateCookieHandler = () => {
    updateCookie(`my-awesome-cookie-${counter}`);
    setCounter(c => c + 1);
  };
return (
    <div>
      <p>Value: {value}</p>
      <button onClick={updateCookieHandler}>Update Cookie</button>
      <br />
      <button onClick={deleteCookie}>Delete Cookie</button>
    </div>
  );
};

9. usePermission

usePermission следует применять для получения permission-статуса API браузера. Передайте имя API, чтобы получить статус.

import {usePermission} from 'react-use';
const Demo = () => {
  const state = usePermission({ name: 'microphone' });
return (
    <pre>
      {JSON.stringify(state, null, 2)}
    </pre>
  );
};

10. useDebounce

Хук используется для задержки события до завершения времени ожидания. В приведенном ниже коде заданное состояние выполняется после завершения времени ожидания:

const Demo = () => {
  const [state, setState] = React.useState('Typing stopped');
  const [val, setVal] = React.useState('');
  const [debouncedValue, setDebouncedValue] = React.useState('');
const [, cancel] = useDebounce(
    () => {
      setState('Typing stopped');
      setDebouncedValue(val);
    },
    2000,
    [val]
  );
return (
    <div>
      <input
        type="text"
        value={val}
        placeholder="Debounced input"
        onChange={({ currentTarget }) => {
          setState('Waiting for typing to stop...');
          setVal(currentTarget.value);
        }}
      />
      <div>{state}</div>
      <div>
        Debounced value: {debouncedValue}
        <button onClick={cancel}>Cancel debounce</button>
      </div>
    </div>
  );
};

11. useGeolocation

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

import {useGeolocation} from 'react-use';
const Demo = () => {
  const state = useGeolocation();
return (
    <pre>
      {JSON.stringify(state, null, 2)}
    </pre>
  );
};

12. useNetworkState

Приведенный ниже код используется для получения сетевого статуса браузера. useNetworkState можно применять для показа пользователю состояния подключения.

import {useNetworkState} from 'react-use';
const Demo = () => {
  const state = useNetworkState();
return (
    <pre>
      {JSON.stringify(state, null, 2)}
    </pre>
  );
};

13. useCopyToClipboard

Хотите скопировать текст в буфер обмена? useCopyToClipboard – именно то, что вам необходимо.

const Demo = () => {
  const [text, setText] = React.useState('');
  const [state, copyToClipboard] = useCopyToClipboard();

  return (
    <div>
      <input value={text} onChange={e => setText(e.target.value)} />
      <button type="button" onClick={() => copyToClipboard(text)}>copy text</button>
      {state.error
        ? <p>Unable to copy value: {state.error.message}</p>
        : state.value && <p>Copied {state.value}</p>}
    </div>
  )
}

14. useFavicon

Крючок useFavicon используется для установки иконки на странице.

import {useFavicon} from 'react-use';
const Demo = () => {
  useFavicon('https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico');
return null;
};

15. useError

Применяйте useError для контроля и отправки ошибок.

import { useError } from 'react-use';
const Demo = () => {
  const dispatchError = useError();
const clickHandler = () => {
    dispatchError(new Error('Some error!'));
  };
return <button onClick={clickHandler}>Click me to throw</button>;
};
// In parent app
const App = () => (
  <ErrorBoundary>
    <Demo />
  </ErrorBoundary>
);

Заключение

В репозитории react-use на GitHub есть еще несколько настраиваемых хуков. Надеюсь, вы сочтете их полезными. Спасибо за внимание!

***

Дополнительные материалы:

Источники

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

eFusion
01 марта 2020

ТОП-15 книг по JavaScript: от новичка до профессионала

В этом посте мы собрали переведённые на русский язык книги по JavaScript – ...
admin
10 июня 2018

Лайфхак: в какой последовательности изучать JavaScript

Огромный инструментарий JS и тонны материалов по нему. С чего начать? Расск...