Ngrx: Как предотвратить потерю данных после обновления состояния в массиве элементов? - PullRequest
1 голос
/ 15 апреля 2019

Приложение My Angular отображает список Item, где каждый Item (Компонент) имеет свое собственное состояние, состоящее из следующих свойств:

{
    name: 'item name',
    status: 'OK'
}

Я использовал хранилище ngrx для поддержания обновленного состояния для каждого компонента (состояние OK поступает из бэкэнд-службы через Effect, поэтому я асинхронно извлекаю данные для помещения в хранилище).

Angular опрашивает бэкэнд-сервис, и если поле состояния для n-го элемента не в порядке, пользовательский интерфейс должен быть окрашен по-другому.

Внутренний сервис возвращает массив элементов указанного выше типа и помещается в list ниже.

Итак, вот государственное представительство:

export interface State {
    list: Item[]
}

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

Так что у меня было бы такое состояние в определенный момент:

[{
    name: 'item 1',
    status: 'OK',
    open: true
},
{
    name: 'item 2',
    status: 'OK',
    open: false
},
{
    name: 'item 3',
    status: 'OK'
}
...
{
    name: 'item n',
    status: null
}]

Свойство open устанавливается событием пользовательского интерфейса. Другие свойства получены из бэкэнда (через массив).

Моя проблема в том, что каждый раз, когда я отправляю действие, которое извлекает данные из серверной службы, все элементы перезаписываются (я четко понимаю почему), и у меня есть это:

[{
    name: 'item 1',
    status: 'OK'
},
{
    name: 'item 2',
    status: 'OK'
},
{
    name: 'item 3',
    status: 'OK'
}
...
{
    name: 'item n',
    status: null
}]

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

Я пытался:

  • использовать другой магазин
  • использовать другой массив в том же хранилище

но я думаю, что у меня будут проблемы с синхронизацией в обоих случаях

  • Я попытался изменить редуктор из этого:
case ItemsActions.STORE_ITEM_LIST:
    return {
    ...state,
    list: action.payload
}

к этому (обновить каждый элемент, указав каждое поле):

case ItemsActions.STORE_ITEM_LIST:
return {
    ...state,
    list: action.payload.map((item, index) => {
        action.payload[index].name === item.name ? {
            ...item,
            name: item.name,
            status: item.status
        } : item
    })
}

1 Ответ

0 голосов
/ 15 апреля 2019

Теоретически вы должны отобразить полезную нагрузку и "соединить" текущее значение состояния с входящим значением.

Это приводит к следующей реализации:

case ItemsActions.STORE_ITEM_LIST:
return {
    ...state,
    list: action.payload.map((item) => ({
            ...state.list.find(item2 => item2.name === item.name) || {}, // if the item isn't found just create an empty object
            name: item.name,
            status: item.status

    }))
}

Чтобы сделать этиобновления проще, вы можете посмотреть на:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...