How to save many development hours in Angular [NgRx/data]
Hey. Welcome. Here I’ll tell you why I chose ngrx/data and why I was so happy with that. You know that incredible joy, special for a developer when you start a new project. You feel that you will no longer make mistakes from past projects and will build something amazing. Utopia.
And it was the same for me. Step by step, we were close to adding some state management to our app. And I know that the app will be brilliant. I know those founders who came up with the idea to help people sell more their products and so feed their families. as any usual startup, they don’t have so much money to buy all fancy libraries or choose free but which need many developer's hours. So I had to do all my best in choosing libs.
In my head, I had two options. NgRx and Akita. I wanted something new. I’ve already worked with NgRx. But I had an unpleasant aftertaste. It’s great, yes! But I was looking for lighter, easier stuff. I wanted to choose Akita as well, but it wasn’t so popular at that time. And for future recruitment, it would be easier to go with NgRx. And I went to NgRx official site. You don’t believe it, but there was a miracle!
NgRx/data — it’s a simplified version of NgRx which is more customizable. For applications that have many entity types, it’s very painful to create, maintain and test every entity type.
I remember when I met Redux for the first time. Actions, selectors, effects, reducers…so much similar code. Come on guys I just need to save my data from the Backend side!
So I was on a project with Angular and NgRx. Learned all dependence, and understood how to write feature store quickly. And I remember how much pain we had with the non-updated store after some user action. Because we saved everything. So my first advice will be:
Don’t save everything in the store or don’t be afraid to reload it.
There is no difference in what pattern you use to store data if you have a mess with it. WHAT TYPE OF DATA BETTER NOT SAVE without often reloading? EASY, temporary data. If you have data that can be easily changed by different filters or users can have many companies — with many teams — in those teams you have team members, maybe you should think better to do one more call. Do you really want to handle up-to-date data in the store? Do you want to spend developers and QAs time on testing it over and over again?
Usually, I save user information like user model
or authorize flag
and permanently data
. Or you need to share something between modules that why having a store it’s a good idea. Let’s return to the main subject.
NgRx/data allows you to avoid writing all actions and effects, reducer
because all that you need it’s a simple service
(with getAll( ) or other methods from NgRx/data).It will call BE and save data but also give you simple selectors to get data. Maybe now you think about how you will know when data is loading or if there is an error?
The good news, NgRx/data manages all that stuff by itself. What this tool can do:
- automates the creation of actions, reducers, effects, dispatchers, and selectors for each entity type.
- provides default HTTP GET, PUT, POST, and DELETE methods for each entity type.
- holds entity data as collections within a cache which is a slice of NgRx store state.
- supports optimistic and pessimistic save strategies ( advanced )
- enables transactional save of multiple entities of multiple types in the same request.
- makes reasonable default implementation choices
I can say that thing will save a lot of your and your’s team members' time! Do you need to add a new feature store? Easy, update the interface of the main store and write service. That’s all. What magic! LIT.
Few steps to have a ready store:
✓ Install
npm i @ngrx/data && npm i @ngrx/effects && npm i @ngrx/entity &&
npm i @ngrx/store && npm i @ngrx/store-devtools
✓ Initialize in a core module
✓ Create defaultDataServiceConfig
Here in entityMetadata
we initialize our features in store, the same as you do with reducer, also we can pass additional things like selectId
function if your object hasn’t id
or sort function. Note: NgRx/data will make a request by root (host) which you mention in defaultDataServiceConfig and the name of features.
(e.g. defaultDataServiceConfig.root/keyNameOfEntetyMetadata
=> http//localhost:400/posts).
You can config request name by creating pluralName:
const pluralNames = { customer: 'customers', posts: 'client-post'};
and pass it EntityDataModule:
IF YOU WANT COMBINE DEFAULT NgRx AND NgRx/DATA, your AppStore interface will be looking like that:
export interface AppStore {
filters: fromFilters.IState // feature created by you
entetyCache: any // additional feature created by ngrx/data}export const AppReducers = {
// feature created by you without ngrx/data
filters: fromFilters.reducer
}
✓ Create a Service
At first, you need to initialize entityService by your feature key (e.g. ‘customer’). As you can see, instead of many files like actions, effects and etc. we can create a small service, and it takes like 10 minutes max. Entity Service gives such things as loaded, loading, error, data
properties. Wow.
Conclusion
If you are tired from writing so many actions/effects but you love having reactive programming — ngrx/data for you. One service and everything is done. There are a lot of prons like caching responses, updating data in the store before the call succeeds, and automatic actions. Don’t forget that you always can combine regular redux and simplified. For me, it was a great decision at that time and I never regret it.