Spec-Zone.ru › React 17

Справочник по хукам

Хуки — это новое дополнение в React 16.8. Они позволяют использовать состояние и другие возможности React, не написав класс.

Хуки являются совместимыми со старыми версиями. На этой странице представлен обзор хуков для опытных пользователей React. Это быстрый обзор. Если вы запутаетесь, найдите жёлтый блок, похожий на этот:

Подробное объяснение

Прочитайте мотивацию, чтобы узнать, почему мы вводим хуки в React.

↑↑↑ Каждый раздел заканчивается жёлтым блоком, подобным этому. Они ведут к подробным объяснениям.

📌 Хук состояния

Этот пример отображает счетчик. При нажатии кнопки значение увеличивается:

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Здесь useState является хуком (мы поговорим о том, что это значит чуть позже). Мы вызываем его внутри функционального компонента, чтобы добавить некоторое локальное состояние. React сохранит это состояние между перерисовками. useState возвращает пару: текущее значение состояния и функцию, позволяющую его обновлять. Вы можете вызвать эту функцию из обработчика событий или из другого места. Это похоже на this.setState в классе, за исключением того, что оно не объединяет старое и новое состояние вместе. (Мы покажем пример сравнения useState с this.state в Использовании хука состояния.)

Единственным аргументом для useState является начальное состояние. В приведенном выше примере это 0, так как наш счетчик начинается с нуля. Обратите внимание, что в отличие от this.state, состояние здесь не обязательно должно быть объектом — хотя оно может быть им, если вы этого хотите. Аргумент начального состояния используется только во время первой отрисовки.

Объявление нескольких переменных состояния

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

function ExampleWithManyStates() {
  // Declare multiple state variables!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

Синтаксис распаковки массивов позволяет присвоить разные имена переменным состояния, объявленным при вызове useState. Эти имена не являются частью API useState. Вместо этого React предполагает, что если вы вызываете useState много раз, вы делаете это в том же порядке при каждой перерисовке. Мы вернёмся к тому, почему это работает и когда это полезно позже.

Что такое хук?

Хуки — это функции, которые позволяют «присоединиться» к состоянию React и функциям жизненного цикла из функциональных компонентов. Хуки не работают внутри классов — они позволяют использовать React без классов. (Мы не рекомендуем переписывать существующие компоненты за одну ночь, но вы можете начать использовать хуки в новых компонентах, если хотите.)

React предоставляет несколько встроенных хуков, например, useState. Вы также можете создавать свои собственные хуки для повторного использования поведенческого состояния между различными компонентами. Сначала рассмотрим встроенные хуки.

Подробное объяснение

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

⚡️ Хук эффекта

Возможно, вы раньше выполняли загрузку данных, подписки или вручную изменяли DOM из компонентов React. Мы называем эти операции «побочными эффектами» (или «эффектами» для краткости), потому что они могут влиять на другие компоненты и не могут выполняться во время отрисовки.

Хук эффекта, useEffect, добавляет возможность выполнения побочных эффектов из функционального компонента. Он служит той же цели, что и componentDidMount, componentDidUpdate и componentWillUnmount в классах React, но объединён в единый API. (Мы покажем примеры сравнения useEffect с этими методами в Использование хука эффекта.)

Например, этот компонент устанавливает заголовок документа после обновления React DOM:

import React, { 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. Эффекты объявляются внутри компонента, поэтому они имеют доступ к его свойствам и состоянию. По умолчанию React выполняет эффекты после каждой перерисовки — включая первую перерисовку. (Мы подробнее обсудим, как это сравнивается с жизненными циклами классов в Использование хука эффекта.)

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

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);

    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

В этом примере React отпишет нас от нашего ChatAPI при размонтировании компонента, а также перед повторным запуском эффекта из-за последующей перерисовки. (Если хотите, есть способ сказать React пропустить повторную подписку, если props.friend.id, переданное в ChatAPI, не изменилось.)

Как и с useState, вы можете использовать более одного эффекта в компоненте:

function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  // ...

Хуки позволяют организовать побочные эффекты в компоненте по связанным частям (например, добавление и удаление подписки), а не принуждать к разделению на основе методов жизненного цикла.

Подробное объяснение

Вы можете узнать больше о useEffect на отдельной странице: Использование хука эффекта.

✌️ Правила хуков

Хуки — это функции JavaScript, но они накладывают два дополнительных правила:

  • Вызывайте хуки только на верхнем уровне. Не вызывайте хуки внутри циклов, условий или вложенных функций.
  • Вызывайте хуки только из функциональных компонентов React. Не вызывайте хуки из обычных функций JavaScript. (Есть ещё одно место, где можно вызвать хуки — ваши собственные пользовательские хуки. Мы поговорим об этом чуть позже.)

Мы предоставляем плагин линтера, чтобы автоматически применять эти правила.

Подробное объяснение

Вы можете узнать больше об этих правилах на отдельной странице: Правила хуков.

💡 Создание собственных хуков

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

Ранее на этой странице мы представили компонент FriendStatus, который вызывает хуки useState и useEffect, чтобы подписаться на онлайн-статус друга. Предположим, мы также хотим повторно использовать эту логику подписки в другом компоненте.

Сначала извлечём эту логику в пользовательский хук под названием useFriendStatus:

import React, { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

Он принимает friendID в качестве аргумента и возвращает, является ли наш друг онлайн.

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

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

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

Пользовательские хуки — это скорее соглашение, чем функция. Если имя функции начинается с «use» и оно вызывает другие хуки, мы говорим, что это пользовательский хук. Конвенция именования useSomething — это то, как наш плагин линтера может находить ошибки в коде, использующем хуки.

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

Подробное объяснение

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

🔌 Другие хуки

Есть несколько менее распространённых встроенных хуков, которые могут оказаться полезными. Например, useContext позволяет подписываться на контекст React без вложенности:

function Example() {
  const locale = useContext(LocaleContext);
  const theme = useContext(ThemeContext);
  // ...
}

И useReducer позволяет управлять локальным состоянием сложных компонентов с помощью редьюсера:

function Todos() {
  const [todos, dispatch] = useReducer(todosReducer);
  // ...

Подробное объяснение

Вы можете узнать больше обо всех встроенных хуках на отдельной странице: Справочник по API хуков.

Дальнейшие шаги

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

Вы также можете ознакомиться со справочником по API хуков и часто задаваемыми вопросами по хукам.

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

Полезен ли эта страница?

© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://17.reactjs.org/docs/hooks-overview.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API