Action Mapping in NgRx #4484
Armenvardanyan95
started this conversation in
Ideas
Replies: 1 comment 2 replies
-
Hello Armen 👋, Why is it not possible to do that in the calendar feature? export const loadEvents = createEffect(() => {
const actions$ = inject(Actions);
return actions$.pipe(
ofType(CalendarActions.calendarViewOpened),
map(() => EventsActions.loadEvents())
);
}, {functional: true})
export const loadTodos = createEffect(() => {
const actions$ = inject(Actions);
return actions$.pipe(
ofType(CalendarActions.calendarViewOpened),
map(() => TodosActions.loadTodos())
);
}, {functional: true}) If I am not mistaken, that is the recommended approach in the lining rule (maybe a class is better here) |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
When building complex applications with multiple libraries (especially using Nx or other tools like it) that utilize NgRx, it often becomes necessary to interact with Actions from other libraries, which you as a developer often do not want (or even don't have the rights) to modify in any way. For instance, consider this example of two applications, one a todo list, and another a calendar. For this purpose, we have a todo-feature library for its store, reducers, etc, and one for the calendar app. Todos feature exports actions like this:
And the calendar actions exports similar actions but for calendar events. But here's the catch, the calendar app also shows the todo items from the other app in the calendar view (using the to do end date). This means, that when I open up the calendar app, I essentially have to dispatch 2 actions:
However, this is considered a bad practice as per the "Avoid dispatching multiple actions sequentially" Rule, with which I wholeheartedly agree. It would be better to have some sort of "event" action like "Calendar View Opened", which would then trigger the respective effects and so on. However, I cannot put that action in either of the store libraries, because, well, it does not belong in the todo library as it is not related to todo items, and it doesn't belong to the events store as it is related to the calendar feature itself and probably belongs in the app itself. I could write an effect in the calendar feature app like the following:
But this is also disallowed by the same rule, with which I also kinda agree.
So, this leaves us with very limited options, none of which are really good
So, to counter this, I propose a discussion for a simple "Action Mapping" feature in NgRx, with which we can define "mappings" or "translations" between existing actions, both the ones in our app and the ones imported from elsewhere. This can look simple like this:
With this, dispatching
CalendarActions.calendarViewOpened
will also mean dispatchingTodosActions.loadTodos
andEventsActions.loadEvents
. We can also provide a way to map the payload of the first action to the result like this:This allows for many things to be easily refactored in an app that uses NgRx, and a way to easily find which action potentially trigger others, and also helps keep feature stores as segregated as possible (which is not a hard requirement, but is still a good practice).
Pros
Const
It is also possible that I am missing something, and maybe a more native solution for the problem I described in the beginning exists. Would love to hear other opinions.
Beta Was this translation helpful? Give feedback.
All reactions