Ngrx store: обновление общего состояния за пределами ActionReducerMap - PullRequest
1 голос
/ 28 мая 2020

У меня есть хранилище ngrx с начальным состоянием, аналогичным:

const state = { 
    child1: {...},
    child2: {...},
}

с ActionReducerMap следующим образом:

const reducerMap = {
    child1: reducer1,
    child2: reducer2,
}

Теперь я хотел бы добавить «загрузка» state на том же уровне, что и child1 и child2, чтобы отслеживать загрузку обоих дочерних элементов (которые связаны между собой). Для этого я обновил начальное состояние следующим образом:

const state = { 
    child1: {...},
    child2: {...},
    loading: false,
}

И я попытался использовать метаредуктор, который находится наверху reducer1 и reducer2 следующим образом:

export function metaReducer(reducer) {
    return function reduce(state, action) {
        switch(action.type) {
            case CommonActionTypes.UpdateLoading: {
                return {
                    ...,
                    loading: action.loading
                }
            }
            default:
                return reducer(state, action);
        }
    }
}

Я добавил это в хранилище функций следующим образом:

StoreModule.forFeature('myStore', compose(metaReducer, combineReducers)(reducerMap))

В приложении я вызываю действия UpdateLoading во время некоторых эффектов, которые обновляют child1 и child2. Однако это не работает так, как я ожидал.

  1. Начнем с того, что начальное состояние вообще не учитывает переменную 'loading' - оно по-прежнему считает, что исходное состояние
{ 
    child1: {...},
    child2: {...},
}
Переменная 'loading' в состоянии обновляется только при вызове действия UpdateLoading. При всех последующих действиях он снимается с состояния. Это странно, поскольку единственный редуктор, который действует на него, - это мета-редуктор, в то время как reducer1 и reducer2 действуют на дочерние состояния child1 и child2 соответственно.

Это правильный подход для обновления общего состояния с использованием метаредуктор? Как я могу заставить это работать?

1 Ответ

0 голосов
/ 29 мая 2020

Попробуйте использовать редуктор в обоих случаях:

export function metaReducer(reducer) {
    return function reduce(state, action) {
        switch(action.type) {
            case CommonActionTypes.UpdateLoading: {
                return reducer({ // <- wrap it.
                    ...state,
                    loading: action.loading
                }, action);
            }
            default:
                return reducer(state, action);
        }
    }
}

А в .forRoot вот так:

StoreModule.forRoot({/*...*/}, {
  metaReducers: [metaReducer],
}),
...