Подтвердить что ты не робот

Как отделить пользовательский интерфейс и состояние приложения в Redux

При написании приложения react-redux мне нужно сохранить как приложение, так и состояние пользовательского интерфейса в глобальном дереве состояний. Каков наилучший подход к его оформлению?

Допустим, у меня есть список предметов todo:

{
  items: [
    { id: 1, text: 'Chew bubblegum' },
    { id: 2, text: 'Kick ass' }
  ]
}

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

{
  items: [
    { id: 1, text: 'Chew bubblegum', selected: true, expanded: false },
    { id: 2, text: 'Kick ass', selected: false, expanded: false }
  ]
}

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

Другим подходом является сохранение другого массива для состояния пользовательского интерфейса элементов:

{
  items: [
    { id: 1, text: 'Chew bubblegum' },
    { id: 2, text: 'Kick ass' }
  ],
  itemsState: [
    { selected: true, expanded: false },
    { selected: false, expanded: false }
  ]
}

Затем вы должны объединить эти два состояния при рендеринге элемента. Я могу представить, что вы можете zip использовать эти два массива в connect для облегчения рендеринга:

const TodoItem = ([item, itemState]) => ...;
const TodoList = items => items.map(item => (<TodoItem item={item} />));

export default connect(state => _.zip(state.items, state.itemsState))(TodoList);

Но обновления состояния могут быть болезненными, потому что items и itemsState должны храниться в синхронизации:

  • При удалении элемента необходимо удалить соответствующее itemState.
  • При переупорядочивании элементов, itemsState также необходимо переупорядочить.
  • Когда список элементов todo обновляется с сервера, необходимо сохранить идентификаторы в пользовательском интерфейсе и выполнить некоторую согласование.

Есть ли другой вариант? Или есть библиотека, которая помогает синхронизировать состояние приложения и пользовательского интерфейса?

4b9b3361

Ответ 1

Другой подход, основанный на normalizr:

{
    ids: [12,11], // registry and ordering
    data: {
        11: {text: 'Chew bubblegum'},
        12: {text: 'Kick ass'}
    },
    ui: {
        11: { selected: true, expanded: false },
        12: { selected: false, expanded: false }
    }
}

Ответ 2

Я сейчас смотрю на это сам для побочного проекта. Я собираюсь приблизиться к нему, как и метод Рика выше. Данные {} служат источником истины, и вы используете это, чтобы вносить локальные изменения ui в (отражающие самое текущее состояние). Вам нужно объединить данные и ui вместе перед рендерингом, и я сам пробовал это в нескольких местах. Я скажу, что если держать в синхронизации, это не должно быть слишком плохо. В принципе, всякий раз, когда вы сохраняете/извлекаете данные, вы обновляете данные {} и очищаете ui {}, чтобы подготовиться к следующему варианту использования.