UI State отличается от остальных видов состояния тем, что относится только к UI и не влияет на остальные части приложения. Например, всплывающая подсказка при наведении мышкой на элемент. В таких ситуациях бывает полезно хранить состояние не в Redux, а внутри компонентов, отвечающих за соответствующий вывод на экран. Преимущества очень простые: не надо создавать действий, не надо задействовать весь механизм диспетчеризации. К тому же перерисовка коснётся только небольшой части виртуального DOM (скорее всего).

Практика показывает, что довольно часто нельзя провести чёткую грань между app state и ui state. Начнём с того, что отображение на экране зависит вообще от всего. Например, в приложениях списка задач, выполненная задача, как правило, отображается зачёркнутой. В данном случае "зачёркнутость" определяется тем, какое значение в свойстве state у соответствующей задачи. Текущий выбранный элемент может быть исключительно элементом UI, а может влиять на поведение программы, например, определённых кнопок, позволяющих выполнять действий в стиле "удалить все выбранное". Вот лишь некоторые примеры, которые можно отнести либо к одной, либо к другой части состояния:

  • Подсвеченный текущий элемент.
  • Элемент в режиме редактирования.
  • Отфильтрованный список.
  • Отображение в три колонки.

Так где хранить UI State?

А вот что говорят по этому поводу разработчики React:

The rule of thumb is: do whatever is less awkward.

Другими словами, делайте так, как наименее тяжело и затратно. По умолчанию исходите из предположения, что всё хранится в Redux. В своей практике я припомню лишь несколько случаев, когда использовалось локальное состояние. В основном такое бывает у сторонних компонентов или в самописных виджетах. Не забывайте, что локальное состояние не участвует в процессе диспетчеризации, а значит его не так легко отлаживать, потому что оно не отображается в DevTools Redux.

Но чего не стоит делать однозначно, так это примешивать app state и ui state в domain data.

const state = {
  tasks: {
    byIds: { 1: { ui: `'opened'` } },
  },
};

Обычно данные приходят с сервера в чистом виде. UI состояние появляется позже, во время взаимодействия с пользователем. Соединяя UI-состояние с самими данными, мы получаем сразу несколько проблем:

  1. Все новые данные придётся обрабатывать, добавляя в них UI-состояние.
  2. Всё, что отправляется на сервер, придётся чистить от UI-состояния.

Ниже приводится пример правильного разделения:

const state = {
  tasks: {
    byIds: { 1: { /* ... */ } },
  },
  tasksUIState: {
    1: { state: 'editing' },
  }
};
Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →