Angular Challenges #7 NgRx Notification
Right now, the app has an implementation that works without the use of ngrx effects.
NgRx Effect is a very powerful library develop by the NgRx team. Effects subscribe to a HOT Observable and listen to any event dispatch from any place inside the application.
Effects can subscribe to ANY observables. We can wrap a hot observable inside an effect and add logic to it.
In this exercice, we will find a way to create a very powerful, scalable and maintainable push messages listener. Currently, the code is located inside a single file with a if else condition to send the push data to the right location. This code is not very scalable since we need to add more and more else, and so not very maintainable since the piece of code will become bigger and bigger.
Also, we load the whole file at startup even if we haven't load some part of the application (lazy loading); and so we don't need to listen or update that part of the store. We need to decouple that logic.
create an injection token to hide the push service implementation.
create one ngrx effect, or component store effect for each push type, and implement your logic
load your effect only when necessary. the application contain a root route, a lazy loaded route and a component with a local state (implemented with Component store)
- There are continually new students, teachers, and schools added.
- You need to implement a notification when an add / update event happens.
- I used an Angular Material snackbar to display the notification messages.
- ngx-toastr is also a good choice to implement the same thing. Toastr makes it slightly easier to distinctly style your notifications.
{dispatch: false}
is necessary for effects that don't dispatch an action.providedIn: root
helps with lazy loading.@ngrx/router-store
-> a help for lazy loading ? I don't think so. Router store replaces the need for activated route. This app doesn't do anything with the url.- Routes can take a providers array.
- Need to investigate
USER_PROVIDED_EFFECTS
. - The SchoolStore is a
ComponentStore
. Component stores have no actions so you can't listen for an action like the other stores. - You can inject the global store into the
ComponentStore
component and dispatch actions using the injected store. - "Moving state up" can help when a component is unreachable.
- effects vs services -> In NgRx, effects essentially replace services (technically, effects are services themselves, as effects use
Injectable
). This leads me to believe the correct way to implement this would be to eliminate the notification service. - You could also eliminate the http service. You would need inject the http service into each component and then inside an
OnInit
, call the correspondinggetAll
method. One drawback to this is thatOnInit
would have a lot of code. - Effects should have single responsibility.
- There are a lot of intermediate actions / services in this app.
- The backend seems like it could be consolidated. But from the directions, it seems like the backend doesn't need to be touched.
- "boiler" effects -> Don't have an effect that listens for an action just for that action to call another effect.
create one ngrx effect, or component store effect for each push type, and implement your logic
- so you can create mutliple effects for each type or create one effect and listen to multiple actions.- Creating one effect that listens to multiple actions is not applicable because the school store is a component store.
- You don't want to perform multiple side effects inside a single effect.
- For this app's basic snackbar implementation, there is one action type that all the different components dispatch. There are metadata strategies in NgRx where a single action is dispatched with extra data that can be checked inside the effect to determine the origin of the action.
- Refactoring to use
createFeature
has limited benefit. The app uses entity adapters to handle each collection. You could better co-locate the code in a one file (reducer), but I don't see much benefit for such a change. - NgRx Entity can be eliminated. You could have a global state with teacher, student, and school arrays. Much like the
AppState
in thefake-db
service. @ngrx/eslint-plugin
doesn't install correctly as a dev dependency when you use theng add @ngrx/eslint-plugin
command.- An injection token approach doesn't seem to be a very NgRx way of adding a notification service. The Component Store component is a huge arbitrary monkeywrench. The school component store is not really dealing with a distinct local state. A selector could very easily provide its template with data.
- If I add an injection token, I would want to try and use a factory to pass the data type to the token. I don't know if you could eliminate the
isTeacher
(etc) checks. Use a filter in the effect? - Better to just pass push service to each component ? Then each component gets its own instance of the service. With the original implementation, the notification service is shared by all components.
- This is Angular - ngrx and lazy loading
- Angular Architects - routing and lazy loading with standalone components
- Ng Serve - tutorial handling user notifications
- Medium - how to manage your notifications in angular ngrx inside effects as side actions
- Github - angular ngrx ngx toastr
- Blog - sharing data between modules is peanuts
- Country Code Ghost - angular injection token use cases
- Medium - mastering injectable services a comprehensive guide
- Medium - ngrx effect use to cache get request
- Blog - ngrx mat snackbar
- YouTube - NGRX/Effects - Display snack bar material UI Notifications | Dispatch multiple actions from effects
- Medium - push based architectures with rxjs
- Offering Solutions - migrating angular to ngrx functional apis and effects
- Medium - how to show a success or failure message after an action dispatched in ngrx
- Stack Overflow - why should I use ngrx if I have signals
- Blog - start using ngrx effects for this
- Angular Experts - level up your ngrx skills with 10 time tested best practices
- Github - Best practices for generic effects #3428 (Discussions)
- Blog - sharing data between modules is peanuts
- Medium - angular routing data with ngrx effects
- Medium - ngrx component store exploration
- Medium - component store 101 main concepts and ngrx store interactions
- Stack Overflow - ngrx component store trigger effect when state changes
- Stack Overflow - ngrx component store trigger effect when state changes
- YouTube - Keeping Side Effects out of your Angular Components with NgRx ComponentStore
- YouTube - NgRx Playlist
- Medium - ngrx effect use to cache get request
- YouTube - Angular NgRx Tutorial | Episode 3 | Lazy loading the store state for a feature module
- Blog - you should take advantage of the improved ngrx apis
- Github - Listen router events using ComponentStore
- Angular Schule - 5 useful effects without actions
- Github - feature module state composition
- Stack Overflow - multiple stores in ngrx
- Dev.to - manipulating ngrx effects
- Initgrep - handle side effects in ngrx
- Capital One - ngrx vs services
- YouTube - NgRx Effects - Avoiding Common Pitfalls
- YouTube - NgRx industry best practices with Tomas Trajan
- Stack Overflow - ngrx effect to call a service when an action occurs (outdated)
- Dev.to - ngrx listening for actions
- Angular In Depth - understanding the magic behind ngrx effects
- Angular Snippets - component store with global state
- Github - Angular eslint
- Blog - an experiment using the global ngrx store as a local store
- Stack Overflow - having different provider for the same injection token
- Angular Docs - Injection Token
- Stack Overflow - how to update dependency injection token value
- Medium - stop being scared of injection tokens
- Stack Overflow - is there anything like app initializer for lazy loaded modules in angular
- Medium - understanding resolvers in angular
- Stack Overflow - dynamic angular service injection for ngrx effect
- Github - feat(effects): add user provided effects to EffectsModule.forFeature #2231
- YouTube - #63 Hierarchical Dependency Injection | Services & Dependency Injection | A Complete Angular Course
- Blog - 6 ways to unsubscribe from observables