В 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, есть несколько проблем, с которыми вы можете столкнуться при его использовании:
- Производительность. Если вы используете
useState
для управления сложными состояниями с большим количеством свойств или если ваш компонент часто отрисовывается, это может повлиять на производительность. В таких случаях лучше использоватьuseReducer
вместоuseState
. - Совместное использование состояния между компонентами. При использовании
useState
может быть сложно обмениваться состоянием между компонентами, которые не находятся в отношениях родитель-потомок. В таких случаях вам может понадобиться использовать библиотеку управления состоянием, такую как Redux или контекстный API. - Обновление сложного состояния: когда вам нужно обновить состояние на основе предыдущего состояния, вам нужно использовать функцию обратного вызова внутри
setState
, чтобы убедиться, что предыдущее состояние используется правильно. С этим может быть сложно справиться при обновлении сложных объектов состояния. - Управление несколькими переменными состояния. Если вам нужно управлять несколькими переменными состояния в одном компоненте, вам придется использовать
useState
несколько раз, что может привести к созданию большого количества шаблонного кода. - Отладка. Отладка проблем, связанных с
useState
, может быть сложной задачей, особенно если у вас много переменных состояния или если вы используете ловушку сложным образом.
Чтобы преодолеть эти проблемы, вы можете рассмотреть возможность использования альтернативного хука, такого какuseReducer
, или библиотеки управления состоянием, такой как Redux, в зависимости от вашего конкретного варианта использования.
Преодоление проблем с useState
React 16.8.0 представил несколько новых хуков для экосистемы реагирования, и один из них — хук useReducer
. Этот хук используется для управления состояниями в сложных или расширенных сценариях, где вам необходимо выполнить несколько переходов между состояниями на основе предыдущих значений состояния или когда у вас есть взаимозависимые переменные состояния. Этот крючок становится удобным, когда,
- У вас есть сложная логика состояния, которая включает в себя несколько подзначений или когда ваше состояние состоит из нескольких значений, которые необходимо обновлять вместе.
- Вам необходимо получить одно значение состояния из другого или выполнить вычисления на основе текущих значений состояния, чтобы обновить состояние.
- Вам нужно передать состояние и возможность его обновления дочерним компонентам через реквизиты.
- Вы хотите обновить состояние на основе произошедшего действия или события, а не напрямую обновлять состояние.
Как работает useReducer
Хук useReducer
в React принимает два аргумента:
- Функция редуктора указывает, как состояние должно обновляться на основе отправленных действий. Функция редуктора также помогает нам гарантировать, что каждый переход состояния является безопасным и допустимым. Функция редуктора принимает два аргумента: текущее состояние и объект действия, и возвращает новое состояние.
- Начальное значение состояния используется для инициализации состояния. Этот аргумент является необязательным, и если он опущен, начальное состояние будет неопределенным.
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 и найдите прекрасную работу