NGRX Actions

v.18

v.18

Fabio Biondi
Google Developer Expert
Microsoft MVP
# What is an action?
An action in Redux is a plain JavaScript object that represents an intention to change the state of the application.
Actions are the only way to communicate with the Redux store and trigger state changes.
Each action must have a type
property, which is a string
that describes the kind of action being performed, and can optionally carry additional data as payload.
# Dispatch Actions
The Store
service exposes the dispatch
function, the utility we'll use to dispatch actions most of the times:
So we can simply add a button in the template and dispatch the increment
action when clicked:
features/counter/counter.component.ts
# DevTools
When the button is clicked you can see a new action in the action history panel.
Opening the Action tab on the right you can also see the type (that is usually the same you see in the history) and its payload (the parameters passed with the action). In this example there is no payload but we'll use it very soon.
The State Tab shows the current state after every dispatch:
But how can we be sure that the state has been changed after the latest action?
We can click on the previous action in the history panel to check the state value at that moment or we can simply use the Diff
tab which notifies us if something has changed.
In this example you can see that nothing has changed (states are equal
) because we only dispatched an action but there is no a reducer that handle it and update the state:
# Handle Actions in Reducers
We previously wrote this reducer:
core/store/counter/counter.reducer.ts
But we can also write the reducer defining a default value, as shown below.
When the application is first initialized, every reducer function is invoked and, at that time, the state is still undefined
.
We then add an initialState
parameter to the function to define the default state when it's undefined
(only the first time) and, very important, we return this state:
Reducers must always return a state, otherwise they may return an undefined
when they are evaluated and it should never happen.
core/store/counter/counter.reducer.ts
In fact the update-reducers
action is automatically dispatched by NGRX when the application starts and all reducers are processed, initializing all their internal states.
So the store is populated with all reducers initial values:
# Update the state
First add a console.log
inside the reducer:
core/store/counter/counter.reducer.ts
Don't worry if the action is typed as any
. We'll fix it later using the createReducer
function.
Any time we dispatch an action, for example clicking the "(+)" increment button, all the reducers will be invoked:
As you can see the reducer always receive the current state, in this case {value: 0}
, and the action (the object {type: increment}
).
Now our goal is to update the state in according to the action type
and can do it by using a switch
statement that checks the type
of action.
In this scenario, when the action type
is increment
, we return an update state, incrementing state.value by 1
:
core/store/counter/counter.reducer.ts
# DevTools Tips
When the increment
action is dispatched you can see how the store is updated by using the State
panel:
And you can also use the Diff
panel to immediately understand what has changed without having to search for it in the store, where it may not be immediately visible, given that it could be very large:
# Handle multiple actions
You don't need to implement the following snippet but it's just an example to help you understand how to handle multiple actions in a single state.
In the next chapter you will learn how to create reducers and actions in less time and safely typed using some NGRX utilities
As you can imagine you can now handle multiple actions, for instance decrement
or reset
, and update the state as you prefer each time these actions are dispatched:
core/store/counter/counter.reducer.ts
So your component may now dispatch the actions in this way:
# This is just the beginning
The concepts learned so far are useful for understanding the basics of Redux but we have not yet used all the utilities and features that NGRX offers us to make our lives much easier.
In the next lessons we rewrite everything using the NGRX API
# Quiz Time
Which is the right syntax to dispatch an action in NGRX?
this.store.emit({ type: 'increment' })
this.store.select({ type: 'increment' })
this.store.dispatch({ type: 'increment' })
# Interactive Demo & Source Code