

My Notebook: Redux & NGRX
source link: https://www.fiyazhasan.me/my-notebook-redux-ngrx/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

State:
So, what do you think of the following simple app?
If I tell you to represent the current state of the app in form of a simple javascript object, how would you approach?
I can only think of two different ways,
let initialState = {
counter: 0,
greeting: 'Hi there!'
}
let initialState = {
state: {
counter: 0,
greeting: 'Hi there!'
}
}
However, I would prefer the first one since they (counter and greeting) don't relate to each other.
If they were instead firstName and lastName , I would have extracted them in a person type.
Action:
Actions are the ways of bringing changes to the current state of the app. Practically it is also a javascript object and contains the following two fields,
- type - A string representing the type of the action.
- payload - Passed in data/information along with the action being taken. Depending on the use case an action may or may not have a payload.
For example,
let uppercaseGreeting = {
type: 'TO_UPPERCASE'
/* payload: ... */
}
Reducer:
Application state is subjected to change. A reducer is a pure function that takes the current state and an action been dispatched upon it. Depending on the action type it produces a new state and returns it. States are immutable. So, whenever we talk about making changes, remember the changes should be made in an immutable way.
const reducer = function(state = initialState, action) {
switch(action.type) {
case 'INCREMENT':
return Object.assign({}, state, { counter: state.counter + 1});
default:
return state;
}
};
The Object.assign() method is used to copy the values of all enumerable own properties - MDN
Whenever an INCREMENT action is dispatched, only the counter property of the current state object is updated. Object.assign() creates a new state object by merging the existing state with the updated state properties.
Store:
As the name suggests, a store stores an application state tree. When creating a store, it should be configured with a root reducer so that it can have a track of the ever changing application state.
In Redux, store is created using the following syntax,
import { createStore } from "redux";
const store = createStore(reducer);
And in NGRX, it is created in the following way,
import { StoreModule } from '@ngrx/store';
@NgModule({
imports: [..., StoreModule.forRoot({ reducer })]
})
For feature modules use forFeature() instead of forRoot()
Dispatching Actions
In Redux the following will dispatch an action to the store,
store.dispatch({ type: 'INCREMENT' });
In NGRX,
import { Store } from '@ngrx/store';
/* Following is a snippet of the constructor part of a component */
constructor(private store: Store<any>) {
this.store.dispatch({ type: 'INCREMENT' });
}
Action Creators:
An action can be wrapped in function to make it portable. Following is an action creator for incrementing the counter,
export const incrementCounter = () => ({ type: 'INCREMENT' });
Dispatching action using action creator would be something like the following,
Redux,
store.dispatch(incrementCounter());
NGRX,
import { Store } from '@ngrx/store';
/* Following is a snippet of the constructor part of a component */
constructor(private store: Store<any>) {
this.store.dispatch(incrementCounter());
}
Get/Select State:
To get the current application state in Redux use the getState()
method,
store.getState();
In NGRX, use select
to get the state associated with a reducer.
import { Store, select } from '@ngrx/store';
constructor(private store: Store<any>) {
this.state$ = store.pipe(select(state => state.reducer));
}
In ngrx, the root reducer is named simply reducer.
Slicing up into smaller states:
In a large scale solution, the whole app state is sliced up into smaller states to make sure they are easily manageable. Each state has its own reducer. The following is the root reducer of our simple app,
export function reducer( state = initialState, action ) {
switch (action.type) {
case 'INCREMENT':
return Object.assign({}, state, { counter: state.counter + 1 });
case 'DECREMENT':
return Object.assign({}, state, { counter: state.counter - 1 });
case 'TO_UPPER':
return Object.assign({}, state, {
greeting: state.greeting.toUpperCase()
});
case 'TO_LOWER':
return Object.assign({}, state, {
greeting: state.greeting.toLocaleLowerCase()
});
default:
return state;
}
}
We can slice it up into two smaller reducers like,
export function counterReducer( state = 0, action ) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
counterReducerexport function greetingReducer( state = 'Hi there!', action ) {
switch (action.type) {
case 'TO_UPPER':
return state.toUpperCase();
case 'TO_LOWER':
return state.toLocaleLowerCase();
default:
return state;
}
}
greetingReducerNote that, we are dealing with individual slices of the application state. So in the counterReducer, the state becomes the counter property itself and has the initial state value of '0' (zero). Same idea goes for the greetingReducer as well.
Combining reducers
counterReducer and greetingReducer can be combined together to yield the application state. In Redux, combineReducers method can be used inside the createStore
method,
import { createStore, combineReducers } from "redux";
const store = createStore(
combineReducers({ counterReducer, greetingReducer})
);
In NGRX,
import { StoreModule } from '@ngrx/store';
import { counterReducer, greetingReducer } from './reducers';
@NgModule({
imports: [
StoreModule.forRoot({ counterReducer, greetingReducer })
]
})
Recommend
-
67
When I start to learn something new I use to read the blog from the community and related video from the conferences but I’m always wondering if I’m doing correctly and if I’m following the best practice so this time...
-
6
NgRx: Patterns and Techniques
-
19
Play by Play: Angular and ngrx In this course, you’ll explore using ngrx with Angular to implement the redux pattern. ...
-
22
Reactive apps with Angular & ngrxTweet27 minutes read...
-
8
Kate Sky talks with John, Ward, and Craig about her experiences mentoring, NgRx, immutability in code, how you decide what to refactor, how to mentor someone entering NgRx, and state management issues.
-
9
-
9
Web Front-end16 minute readA Deep Dive Into NgRx Advantages and Features
-
13
NGRX: State management in Angular Knoldus Blog Audio Reading Time: 5 minutes Do w...
-
7
ngRx with Redux in Angular Reading Time: 4 minutes In this blog, we will see the basic pattern of Redux and some benefits and some high-level concepts of redux and then we will discuss the brief about ngRx and...
-
6
About this Episode Armen and Chuck discuss the ESLint NGRx plugin. They go over what it adds to ESLint and some of the things that you should be looking for as you write NGRx code in order to make it more uniform,...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK