How can i access (read) the state of a reducer state within a another reducer in NGRX? It is a very similar question to this. Does NGRX offers any other solution to this?
-
1can you be more specific? In general you shouldn't do that! The Reducer MUST be a pure function. Can you explain what you are tring to achive? – ALGDB Nov 28 '18 at 12:55
-
i don't want to change the state in the other reducer, just to read it. My reducer logic require to know about some state that reside inside a different reducer – amit Nov 28 '18 at 13:32
-
1a pure function can only use its parametrs, this means "state" and "actions". what you can do the stay in the "Redux" pattern is to add to the paylod the pice of state you need by selecting it inside an Effect `(withLatestFrom(store.pipe(select(selector))))` an then use the value in the reducer – ALGDB Nov 28 '18 at 13:41
-
Sorry but by "reducer" you mean a pice of state right? – ALGDB Nov 28 '18 at 13:44
1 Answers
I just stumbled upon this question when thinking about doing something similar. I needed a copy of some state information from a different reducer as a temporary "editing" data set that could be canceled and reverted back to the "recorded" data set.
I ended up extending my UI reducer (the reducer that held the state/edits for the current user's session) to include a property to hold a copy of data from my Data reducer (the reducer that represents what is stored in the database). That data gets passed in via a "Start" action.
Here is an abbreviated copy of my UI action:
import { Action } from "@ngrx/store";
import {
ICableFeature
} from "../../shared/models";
export enum UIActionTypes {
...
UI_EDIT_CUSTOM_TAGS_START = "[UI] Edit Custom Tags Start",
UI_EDIT_CUSTOM_TAGS_UPDATE = "[UI] Edit Custom Tags Update",
UI_EDIT_CUSTOM_TAGS_SAVE = "[UI] Edit Custom Tags Save",
UI_EDIT_CUSTOM_TAGS_SUCCESSFUL = "[UI] Edit Custom Tags Successful",
UI_EDIT_CUSTOM_TAGS_FAILED = "[UI] Edit Custom Tags Failed",
UI_EDIT_CUSTOM_TAGS_CANCELED = "[UI] Edit Custom Tags Canceled"
}
...
export class EditCustomTagsStart implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_START;
constructor(public payload: ICableFeature) {}
}
export class EditCustomTagsUpdate implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_UPDATE;
constructor(public payload: ICableFeature) {} // This payload has a copy of the data I needed from the other reducer. Make sure it is a copy and not the same object!
}
export class EditCustomTagsSave implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_SAVE;
constructor() {}
}
export class EditCustomTagsSuccessful implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_SUCCESSFUL;
constructor() {}
}
export class EditCustomTagsFailed implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_FAILED;
constructor(public payload: string) {}
}
export class EditCustomTagsCanceled implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_CANCELED;
constructor() {}
}
export type UIActions =
...
| EditCustomTagsStart
| EditCustomTagsUpdate
| EditCustomTagsSuccessful
| EditCustomTagsFailed
| EditCustomTagsCanceled;
And here is an abbreviated copy of my UI reducer:
import * as fromUI from "../actions/ui.actions";
import {
IOrchestratorState,
IOrchestratorStatusState,
ICableFeature
} from "../../shared/models";
export const uiFeatureKey = "ui";
export interface State {
showScroll: boolean;
fillingGaps: boolean;
fillGapStatus: IOrchestratorStatusState;
currentFillGapState: IOrchestratorState;
editingCustomTags: boolean;
customTagEdits: ICableFeature;
}
export const initialState: State = {
showScroll: true,
fillingGaps: false,
fillGapStatus: null,
currentFillGapState: null,
editingCustomTags: false,
customTagEdits: null
};
export function reducer(state = initialState, action: fromUI.UIActions) {
switch (action.type) {
...
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_START:
return {
...state,
editingCustomTags: true,
customTagEdits: action.payload // This is a copy of the data I needed from the other reducer
};
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_UPDATE:
return {
...state,
customTagEdits: action.payload // This is the updated information from user edits, not saved.
// I can also create a router guard that checks to makes sure the data in this
// property and the data in my Data store are the same before the page is deactivated
};
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_SUCCESSFUL:
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_FAILED:
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_CANCELED:
return {
...state,
editingCustomTags: false,
customTagEdits: null
};
default:
return state;
}
}
As you can see, by passing the data from one reducer to the other as payloads in actions, I am able to maintain pure functions in my reducers.
I hope this helps!

- 7,201
- 13
- 64
- 111