NGRX provides a centralized store to manage the state of your Angular applications:
Built on Redux pattern, a very well know pattern used especially in the React ecosystem to manage global states in your (large and enterprise) applications: so if you have already used it in React, NGRX should be familiar.
Single Source of Truth: All state is managed in a single store, ensuring consistency.
Separation of Concerns: each phase of the state management is isolated promoting modularity, maintainability, and scalability in Angular applications.
Time Travel Debugging: one of my favourite features is the ability to use Redux Dev Tools, an amazing tool to track and reproduce every step of your application knowing exactly what is happening in every moment of the application lifecycle.
But let's go into more detail and start from the basics.
An NGRX store is a central repository for managing the state of an Angular application using the principles of Redux :
Redux Principles
Single Source of truth: the store
State is Read Only
Changes are made with pure function (by invoking actions and updating the store by reducers)
More info about the concept of pure functions are available in a dedicated lesson later in the book
The store acts as a single source of truth for the application state, ensuring that all parts of the application share a consistent and predictable state.
The store is a plain JavaScript object that represents the state.
The store can (ONLY!) be updated through actions and reducers.
Actions are dispatched to express the intent to change the state.
Reducers are pure functions that define how the state should change in response to these actions.
By using selectors, the store allows for efficient querying and retrieving of specific parts of the state, facilitating the separation of concerns and enhancing maintainability.
This architecture promotes a unidirectional data flow, making the state changes traceable and easier to debug, and supports features like Time Travel debugging with tools such as Redux Dev Tools
What can we save in the store?
Various types of data can be saved in an NGRX store:
Entities: collections of items such as users, products, or posts, often managed using entity adapters for efficient CRUD operations.
UI State: data that control the state of the user interface, such as loading indicators, error messages, and form states. But also if a modal has been opened, if the sidebar has been toggled, notification messages and so on...
Authentication Information: Objects related to user authentication and authorization, including tokens, user profiles, and roles.
Configuration Settings: Application-wide settings or preferences that need to be accessed globally.
Session Data: Temporary data related to the current session, such as search queries or pagination information.
Feature Flags: Objects that enable or disable features based on conditions, allowing for dynamic control of application behavior.
NGRX is best suited for more complex applications rather than simple ones.
Consider using NGRX when:
Complex UI Synchronization: Your application has a view/UI with many components that need to stay in sync.
Data Sharing Across Routes: You need to share complex and multiple data across different routes within your application.
State Snapshots: You require capabilities like tracking bugs, rehydrating the store, or implementing undo/redo functionality.
Long-Lifecycle Applications: Your application has a long lifecycle and needs robust state management over time.
Larger Teams: Your frontend team consists of more than 2-3 people, benefiting from a consistent state management pattern.
Common State Management Pattern: You prefer using a common, established pattern to handle application state effectively.
Examples
E-commerce Backoffice: Managing the state of clients, user authentication, invoices, product inventory, filters, pagination and a lot of other states, often in the same page, in a scalable and consistent manner.
OnLine Editors: photo or magazine editors, site builders and other "No and Low Code tools" often need to handle hundred of states
Project Management Tool: Handling complex state transitions for tasks, user assignments, and project timelines with real-time updates and collaboration features.
Social Media App: Coordinating the state for user profiles, posts, comments, and notifications, ensuring smooth data flow and consistency across different components.
Online Banking System / Fintech: Managing user accounts, transactions, and real-time updates for balance and account activity, maintaining security and consistency.
Imagine an application with a shopping cart where you may have separate services for authentication, user information, product details, cart operations, filters and so on:
Now, if a user adds a product to the cart, you need to update the cart state, possibly update user preferences, and maybe even notify other components. With multiple services, you must ensure all these updates are synchronized, which can be error-prone and complex.
Of course we also have to handle authentication, roles, payments and more...
And that's just a "simple" scenario. Things can easily get complicated!
Separation of Concerns since each phase of the state management is isolated
Centralizing state management, ensuring consistency, predictability, and maintainability
Predictable State Updates: Using actions and reducers, state updates are predictable and easier to trace.
Easier Debugging: Tools like Redux DevTools make it simpler to track state changes and debug issues.
Improved Testability: With a single store, mocking state and actions becomes straightforward, improving testability.
Better Performance: Centralized state management allows for better performance optimization. All your components can use onPush change detection strategy
Learning Redux and NGRX can be challenging.
NGRX is not the simplest pattern for manage states but things have gotten simpler in latest NGRX versions and there are now several utilities that make it easier to configure and use.
RxJS is particularly difficult, especially for beginners.
In previous version of NGRX everything was based on Observables, so you had to master it.
Now you can use signals but you still need to have a good foundation in RxJS to manage side effects.
Significant boilerplate code is required.
It's obvious. Create a service that contains a signal requires few minutes while create a file to handle actions, another one for the state, another one for the effects, gets more time.
So tasks can take longer to complete.
But I assure you that the time spent on the initial boilerplate is amply repaid when you have to rework that code.
Not all team members may be able to use and understand it effectively.
There is no improvisation here. We have to follow certain rules that every developer must know in order to work with NGRX.
But this is also an advantage since it is a pattern that the whole team can follow and understand
I recommend you read this page again after you have completed reading the entire chapter
# Decoupling the UI from State Management with NGRX
In an NGRX-powered application, the UI is elegantly decoupled from the underlying architecture through a robust state management pattern.
By centralizing the application's state in a single store, NGRX allows UI components to focus solely on rendering and user interaction.
Components dispatch actions to update the state or trigger a side effect (i.e. an asynchronous operation), while selectors enable them to retrieve the necessary state slices from the store.
This separation of concerns ensures that the business logic and state transformations are handled by reducers and effects, keeping the UI layer simple, declarative, and reactive. Consequently, the decoupling facilitates easier testing, maintenance, and scalability, empowering developers to enhance the user experience without entangling it with the complex mechanics of state management and business logic.
I think that this approach is great when several front-end developers work in the same project.
The clear separation between UI and architecture facilitates collaboration in teams composed of junior, senior developers and architects.
Some developers can take care of the components, build forms and the UI in general without worrying about everything that concerns the architecture which will be managed by other developers instead.