вступление

Хуки появились в версии React 16.8. Это волшебное обновление React сделало классы почти устаревшими, поэтому многие разработчики с тех пор используют хуки и не оглядываются назад.

В этой статье вы узнаете:

  • Что такое крючки
  • Основы использования State Hook
  • Сохранение функций и использование предыдущего состояния
  • Ленивое начальное состояние
  • Спасение от обновления состояния
  • Установщики состояния Prop Drilling
  • Использование хука useState с TypeScript

Что такое крючки?

Хук — это специальная функция, которая позволяет вам добавить некоторое состояние к функциональному компоненту.

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

  • являются функциями
  • импортируются из пакета React, например. import { useState } from “react”;
  • позволяют использовать функции состояния и жизненного цикла React из функциональныхкомпонентов.
  • не работать внутри классов

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

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

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

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

Правила использования хуков React

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

Хороший плагин для линтера, рекомендованный командой React, находится здесь плагин для линтера.

Основы хука useState

Вероятно, это самый используемый хук в React. Этот хук позволяет нам отслеживать состояние функционального компонента.

Состояние относится к данным или свойствам, которые необходимо отслеживать в приложении. Это может быть простое целое число, строка, массив объектов и т. д. Простой вариант использования показан ниже:

import React, { useState } from "react";

const UseStateHookExample = () => {
  const [count, setCount] = useState(0);

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

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

В строке 4 мы объявляем наш хук. Вот несколько вещей, которые нужно знать:

  • Вызывая useState Hook, мы объявляем «переменную состояния». Его можно назвать любым словом, которое вы хотите, а не только «счет».
  • Нам нужно указать только один аргумент для useState Hook. В этом случае мы поставили ноль. Это будет наша начальная переменная.
  • Хук useState возвращает значения «count» и «setCount». «Count» — это наша реактивная переменная, которую мы можем отображать в нашей возвращаемой функции. «setCount» — это функция, которая мгновенно обновляет переменную «count».
  • Когда используется функция setState, наш компонент перерисовывается.
  • Возвращаемые значения заключены в скобки «[ ]», потому что мы используем «деструктурирование массива». Вы также можете сделать это, но не должны:
const UseStateHookExample = () => {
  const count = useState(0);
 
  return (
    <div>
      <p>You clicked this button {count[0]} times</p>
      <button onClick={() => count[1](count[0] + 1)}>Click me for magic</button>
    </div>
  );
};

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

Сохранение функций и использование предыдущего состояния

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

const CounterExample = ({initialCount}) => {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Set count to initialCount</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

Другой пример: у нас есть объект в качестве начального состояния и мы хотим обновить в нем только один параметр. Мы можем использовать оператор распространения JavaScript, чтобы помочь нам вот так:

const UserInformation = () => {
  const [user, setUser] = useState({
    name: "Julia Roberts",
    age: 35,
    gender: "female",
    eyeColor: "blue",
  });

  return (
    <>
      <h1>User {user.name}</h1>
      <p>
        Age is {user.age}, gender is {user.gender}, eyeColor {user.eyeColor}.
      </p>
      <button
        type="button"
        onClick={() =>
          setUser((previousState) => {
            return { ...previousState, age: 39 };
          })
        }
      >
        39
      </button>
    </>
  );
};

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

Ленивое начальное состояние

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

const Component = () => { 
  const [state, setState] = useState(getInitialHundredItems()) 
}

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

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

const Component = () => { 
  const [state, setState] = useState(getInitialHundredItems) 
}

Or

const Component = () => {
  const [state, setState] = useState(() => {
    const initialState = someExpensiveComputation(props);
    return initialState;
  });
}

Спасение от обновления состояния

Что произойдет, если вы обновите состояние до того же значения, что и текущее состояние? React использует алгоритм сравнения Object.is(), который определяет, являются ли два значения одним и тем же значением. Это означает, что React не будет отображать дочерние элементы компонентов или запускать какие-либо эффекты.

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

Установщики состояния опорного бурения

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

В приведенном ниже примере есть два компонента: корневой компонент приложения и компонент Count.

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

const Count = ({ count }) => {
  const [num, setNum] = useState(count);
  useEffect(() => {
    setNum(count);
  }, [count]);
  return <p>{num}</p>;
};
export default function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <Count count={count} />
    </div>
  );
}

Хук UseState и TypeScript

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

React useState Hook обычно автоматически выводит неявный тип возвращаемого состояния из начального состояния. В приведенном ниже примере Typescript знает, что тип «count» — это число:

const [ count, setCount ] = useState(0)

Однако при работе со сложными типами, такими как объекты или типы объединения, мы должны использовать интерфейсы или объекты типа, как показано ниже:

interface UserFormState {
  email: string;
  password: string;
}

const App = () => {
  const [userForm, setUserForm] = useState<UserFormState>({
    email: “”,
    password: “”,
  });
};

Естественно, если не указать начальное значение, значение будет неопределенным:

Const [count, setCount] = useState();

Если тип объявлен, но начальное состояние пусто, count будет числом | неопределенный:

const [count, setCount] = useState<number>();

Если начальное значение представляет собой пустой массив без вывода о типе, тип будет never[].

const [arrayOfString, setArrayOfStrings] = useState([]);

Таким образом, тип настройки имеет решающее значение:

const [arrayOfStrings, setArrayOfStrings] = useState<string[]>([]);

Передача setCount в дочерние реквизиты

Передача свойств дочерним компонентам — распространенный способ обмена состояниями. Однако какой тип имеет setState? Ответ

React.Dispatch<React.SetStateAction<number>>

Таким образом, примером двух компонентов может быть:

function Parent() {
  const [count, setCount] = useState(0);
  return <Child count={count} setCount={setCount} />;
}

interface ChildProps {
  count: number;
  setCount: React.Dispatch<React.SetStateAction<number>>;
}
function Child({ count, setCount }: ChildProps) {
  return (
    <>
      <div>{count}</div>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>
        +
      </button>
    </>
  );
}

Заключение

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

Создавайте приложения React с повторно используемыми компонентами, такими как Lego.

Инструмент с открытым исходным кодом Bit помогает более чем 250 000 разработчиков создавать приложения с компонентами.

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

Подробнее

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

Микро-интерфейсы

Система дизайна

Совместное использование кода и повторное использование

Монорепо

Узнать больше