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

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

import React, { useState } from 'react';

export default function Example() {
  const [title, setTitle] = useState('');
  const [description, setDescription] = useState('');
  return (
    <div>
      <h1>useState example</h1>
      <h1>{title}</h1>
      <p>{description}</p>
      <br />
      <input value={title} onChange={(e) => setTitle(e.target.value)} />
      <br />
      <textarea
        value={description}
        onChange={(e) => setDescription(e.target.value)}
      />
    </div>
  );
}

Приведенный выше код демонстрирует распространенный вариант использования useState. Оба компонента input и textarea используют свои события onChange для обновления состояния title и description с помощью перехватчиков useState.

Недостатки использования useState

Хотя useState — мощный и широко используемый хук в React, есть несколько проблем, с которыми вы можете столкнуться при его использовании:

  1. Производительность. Если вы используете useState для управления сложными состояниями с большим количеством свойств или если ваш компонент часто отрисовывается, это может повлиять на производительность. В таких случаях лучше использовать useReducer вместо useState.
  2. Совместное использование состояния между компонентами. При использовании useState может быть сложно обмениваться состоянием между компонентами, которые не находятся в отношениях родитель-потомок. В таких случаях вам может понадобиться использовать библиотеку управления состоянием, такую ​​как Redux или контекстный API.
  3. Обновление сложного состояния: когда вам нужно обновить состояние на основе предыдущего состояния, вам нужно использовать функцию обратного вызова внутри setState, чтобы убедиться, что предыдущее состояние используется правильно. С этим может быть сложно справиться при обновлении сложных объектов состояния.
  4. Управление несколькими переменными состояния. Если вам нужно управлять несколькими переменными состояния в одном компоненте, вам придется использовать useState несколько раз, что может привести к созданию большого количества шаблонного кода.
  5. Отладка. Отладка проблем, связанных с useState, может быть сложной задачей, особенно если у вас много переменных состояния или если вы используете ловушку сложным образом.

Чтобы преодолеть эти проблемы, вы можете рассмотреть возможность использования альтернативного хука, такого какuseReducer, или библиотеки управления состоянием, такой как Redux, в зависимости от вашего конкретного варианта использования.

Преодоление проблем с useState

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

  1. У вас есть сложная логика состояния, которая включает в себя несколько подзначений или когда ваше состояние состоит из нескольких значений, которые необходимо обновлять вместе.
  2. Вам необходимо получить одно значение состояния из другого или выполнить вычисления на основе текущих значений состояния, чтобы обновить состояние.
  3. Вам нужно передать состояние и возможность его обновления дочерним компонентам через реквизиты.
  4. Вы хотите обновить состояние на основе произошедшего действия или события, а не напрямую обновлять состояние.

Как работает useReducer

Хук useReducer в React принимает два аргумента:

  1. Функция редуктора указывает, как состояние должно обновляться на основе отправленных действий. Функция редуктора также помогает нам гарантировать, что каждый переход состояния является безопасным и допустимым. Функция редуктора принимает два аргумента: текущее состояние и объект действия, и возвращает новое состояние.
  2. Начальное значение состояния используется для инициализации состояния. Этот аргумент является необязательным, и если он опущен, начальное состояние будет неопределенным.
const [state, dispatch] = useReducer(reducer, initialState);

Здесь state представляет текущее значение состояния, а dispatch — это функция, которая используется для отправки действий редуктору. Когда действие отправляется, функция редуктора вызывается с текущим состоянием и объектом действия и возвращает новое значение состояния. Затем обновленное состояние сохраняется state, и все компоненты, использующие это состояние, будут повторно визуализированы с новым значением состояния.

Рефакторинг useState с помощью useReducer

Давайте посмотрим, как провести рефакторинг useState с хуками useReducer.

import React, { useReducer } from 'react';

export default function Example2() {

  const [{ title, description }, updateEvent] = useReducer(
    (prev, next) => {
      return { ...prev, ...next };
    },
    { title: '', description: ''}
  );

  return (
    <div>
      <h1>useState example</h1>
      <h1>{title}</h1>
      <p>{description}</p>
      <br />
      <br />
      <input
        value={title}
        onChange={(e) => updateEvent({ title: e.target.value })}
      />
      <br />
      <br />
      <textarea
        value={description}
        onChange={(e) => updateEvent({ description: e.target.value })}
      />
    </div>
  );
}

Здесь мы можем использовать метод updateEvent, возвращаемый хуком useReducer, для обновления состояния через событие onChange в компоненте ввода и текстовой области. Обратите внимание, что внутри каждого onChange мы используем метод updateEvent и передаем только необходимое состояние, которое необходимо обновить. Также обратите внимание, что первый аргумент (функция редуктора) возвращает новый объект, который включает в себя предыдущее и новое состояния. Мы можем ввести некоторые новые функции в эти функции редуктора, чтобы гарантировать, что каждый переход состояния безопасен и действителен, как показано ниже.

const [{ title, description }, updateEvent] = useReducer(
    (prev, next) => {
      let state = { ...prev, ...next };
      
      if (state.title.length > 100) {
        state.title = state.title.substring(0, 100);
      }
  
      return state;
    },
    { title: '', description: ''}
  );

Здесь мы добавили условие, которое позволяет использовать только первые 100 символов для заголовка. Вы даже можете пойти дальше и добавить больше логики с помощью оператора switch для обработки более сложных состояний.

const [{ title, description }, updateEvent] = useReducer(
    (prev, next) => {
      let state = { ...prev, ...next };
      switch(next.some_action){
       case "MY_ACTION" :
        // Do something
        break;
       default:
        return state;
      }
    },
    { title: '', description: ''}
  );

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

Заключение

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

Если вам нравится мой контент, пожалуйста, сделайте мне одолжение и приготовьте чашечку кофе для вас и меня!

Ваше здоровье!

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







Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 💰 Бесплатный курс собеседования по программированию ⇒ Просмотреть курс
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу