If your application is big enough to use Angular, it is big enough to use NgRx
Of course, this is my opinion, and in general this is an opinionated article, but I will try my best to provide arguments why I think it is right for every Angular application to use NgRx
Of course, if you have a team of people that have never worked with NgRx, starting a new project using another technology (and a new way of thinking!) can seem like a big challenge; and surely, some aspects of reactive programming and Flux design pattern (and the need to use RxJS extensively) can be somewhat confusing, but my experience with NgRx made me think, that with some dedication it is possible to switch from an imperative mindset to functional programming. It is truly possible to come to a decent level of understanding of Flux (and NgRx) within several days, because:
Concepts are not as complex as they sound at first. Actions, Reducers and Effects are scary words, it seems, but in reality, an action is a unique object representing an event in state, a reducer is a pure function that changes the state according to an action (pure functions are especially easy to understand) and so on. In essence, learning NgRx is not very easy, but it is not as challenging as learning an entire new framework like Angular itself; and definitely worth the time invested in it.
Once one of the concepts is mastered, the next is much easier to understand. When you learn about actions, and then see them dispatched, it becomes easy to understand what a reducer is, then what a selector is, and after we have learned all of those concepts, it will be easy to understand Effects, and then suddenly we know NgRx and use on a daily basis.
Note: I would suggest not using NgRx only when there is a lack of
basic knowledge of RxJS; but if you know basic operators
(map/filter/startWith) and Observable combination
(combineLatest/mergeMap), you are good to go to start learning NgRx
So basically NgRx is not as hard to learn as one might imagine, and learning it will yield immense benefits. So if your (or your teams) policy on NgRx is "it is too much overhead to learn and switch to it", then it is time to rethink that policy.
NgRx allows us to have three important things in our applications:
A single source of truth for all our data. This means we can easily understand where and when the data changed and how it affected our UI. Because of its centralized structure, problems are easy to detect: if the state changes in an unexpected way, then the problem is in the reducer function; if the state is transformed in a wrong way, then the problem is in the selector; and so on.
It provides a clear, almost mechanical pathway of solving frontend related challenges, making applications extremely scalable. In other words, NgRx provides a simple, yet very strict structure for how our frontend application should function (even on the folder structure level). It also makes 90% of tasks and UI pieces very straightforward.
Because of its awesome devtools it is very easy to debug, follow, and understand when and where something went wrong.
Essentially these three points help us have an application that is as maintainable and scalable as possible. And this is not something theoretical - you will become convinced of this as soon as you get your first feature requirement change after a certain feature is already built. Imagine scenario: we have an app where once a user selects a value from a dropdown in one component, an HTTP request is performed, and if it is successful, another HTTP request should be performed and update a piece of UI in another component.
Now imagine changing the codebase according to this requirement in an application that does not use NgRx. First we would need a transport mechanism to notify the other component of the dropdown value change (a service-with-a-subject or something like that), then we would need to subscribe to that notification in the other component (and don't forget to takeUntil to unsubscribe!), then inject a new data service into that component, perform the HTTP call, get the data, store in the local state, update UI. Lots of steps, is it not?
Now imagine the same in NgRx: if the state is already selected in the second component, we would just need to dispatch another action in the corresponding Effects class (probably 1-3 lines of code); if not, then add a select method call (most probably just 1 line of code) and it is all done. Understandable, clean, easy to reason about, almost bug free.
Sometimes developers may think that introducing a new framework of thinking will just increase complexity and make applications harder to navigate and perceive.
But the NgRx experience proves yet again that it is better to have more lines of code that are explicit and strict, rather than a short, but disorganized one. Without NgRx, the application's overall situation is not readily understandable. It is not clear, on what data the components depend, also, it is hard to tell only from code, how components affect each other. But with NgRx, the connections are very clear, data flows only from one place, through one place, and is immutable. All of this makes our applications very easy to get into; if you want to know how the state can change, take a look at action names; if you want to know exactly how, read the reducer function (which is usually very obvious - as most pure functions are); if you want to know which data is loaded from external sources, read an Effect.
NgRx is not just a library or a tool - it is a way of thinking, and before you start doing it, there is a learning curve to ascend, and concepts to accept; but in the end, when the learning process is done, you will find out how much it benefits your development process. In several months, it will be harder to do Angular without NgRx.