Installation, store & reducers

v.18

v.18

Fabio Biondi
Google Developer Expert
Microsoft MVP
# Install NGRX v.18
Open terminal in your project root folder and run this command to install and configure NGRX store.
We can use the useful add
CLI command that not only install all the necessary dependencies but often it's automatically configure the library.
Run the command and press YES
to confirm:
Angular v.19 & NGRX v.18
Currently Angular v.19 has been released while NGRX is still at version 18 and they are not compatible.
If your project uses Angular v.19 and NGRX v.19 has not yet been released (should be released within days), you can use this command instead, to install NGRX v.19 RC (release candidate)
The command installs all the dependencies and it also adds provideStore
to providers
array in app.config
:
# Redux Dev Tools package
We talked about Redux Dev Tools in the
previous lessons so it's time to configure it in our project.
Redux DevTools has its own package so we need to install..
Run the command and press YES
to confirm:
The command automatically configures provideStoreDevtools
with some default options in the providers
array of app.config.ts
:
maxAge
indicates the total number of actions to save in history
# Redux DevTools Extension
Now it's time to install the Redux Dev Tools browser extension, useful to monitoring, debugging and tracking everything in your application:
In this book (and in real life), I'll use Chrome.
Open your browser's Dev Tools and you should see the Redux Tab:
If you don't see the Redux Tab, close and re-open your Dev Tools
# Store
In NGRX, the store is a centralized place where the application's state is managed.
The state is a simple plain old JavaScript object typically structured in a way that reflects the different parts of the application, allowing clear separation of concerns and maintainable code.
# Reducers
Reducers are pure functions that determine how the state changes in response to actions.
A pure function is a function that, given the same input, will always return the same output and has no side effects. This means it doesn't alter any external state or rely on any external data. Structuring the store in reducers provides several benefits. Read the
lesson on "Immutability" to get more info about it
-
Separation of Concerns
Each part of the state is managed by its own reducer, making it easier to reason about state changes. For example, a counterReducer
would manage the counter state, a usersReducer
would manage the users state, and a modalReducer
would manage the modalIsOpened state.
-
Scalability
As the application grows, new state slices can be added with their own reducers without affecting existing ones. This modular approach ensures the application remains maintainable and scalable.
-
Predictability
Reducers are pure functions, meaning they always produce the same output given the same input. This predictability makes it easier to debug and test state changes.
-
Single Source of Truth
The store serves as a single source of truth for the application's state, ensuring consistency and reliability across different components and routes.
# Initialize and populate the store
In the next script we define a new reducer that creates a new property home
in the root of the store and it simply holds an array of numbers:
Open Redux DevTools, select the first built-in action @ngrx/store/init
and open the State Tab. You'll have the confirmation that the home
state is in the store
provideState vs provideStore
Although we can register reducers in the provideStore
function:
provideStore({ /* storeConfiguration */ })
the NGRX team recommends keeping provideStore()
empty and using several provideState()
functions to register states in the root providers array.
# Multiple States
You can add as many reducers as you want.
Here we add a new counter
reducer that contains an object with value: 0
:
# Reducer
As you can see a reducer is a simple function:
So it can also be defined as an external function:
Reducers in external files
Of course reducers can also be defined in an external file.
So create a new file counter.reducer.ts
in the src/app/core/store/counter
folder:
core/store/counter/counter.reducer.ts
And now you can import it in app.config.ts
:
The result is the same:
# Quiz Time
Which is the right syntax to define and add a reducer to the store?
provideState({ name: 'home', reducer: [1, 2, 3] })
provideState({ name: 'home', reducer: () => [1, 2, 3] })
# Interactive Demo & Source Code