SlideShare a Scribd company logo
1 of 19
Download to read offline
NG-RX
STATE MANAGEMENT IN ANGULAR
ABOUT ME
SUWIGYA RATHORE
▸ Front end developer with 7+ years of experience
▸ Working for Non Dutch from Sep 2018
▸ Working on Angular from starting almost 2+ years
▸ Have experience of 2 years with largest customer facing Angular website Air
France & KLM (probably Air Kenya, Joon, Transavia etc.)
▸ Working with dffrntmedia on Earthtoday.com
▸ Loves to travel
▸ Read and experiment about latest technologies
▸ Loves to do binge watching on Netflix
RULE 4: REDUX SHOULD THE MEANS OF
ACHIEVING A GOAL, NOT THE GOAL
RULE 5: ALWAYS TREAT ROUTER AS THE SOURCE
OF TRUTH
Victor Savkin
NG-RX
https://blog.nrwl.io/managing-state-in-angular-applications-22b75ef5625f
3
GOLDEN RULES
TEXT
AGENDA
▸ State and reducer setup
▸ NG-RX Store setup @ngrx/store
▸ Accessing State in Component
▸ Redux devtools with angular @ngrx/store-devtools
▸ Collection management @ngrx/entity
▸ Dispatching strongly typed actions
▸ State selectors
▸ Async operations with effects @ngrx/effects
▸ Improve server communication with NX data persistence layer @nrwl/nx
▸ Connect Related data models
▸ Folder structure in project & demo
4
NG-RX
export interface FeatureAState {
projects: Project[],
selectedProjectId: string | null;
}
export const initialFeatureAState: FeatureAState = {
projects: initialProjects,
selectedProjectId: null
}
export function featureAReducer(
state = initialFeatureAState, action): FeatureAState{
switch(action.type) {
default:
return state;
}
}
)
CREATING INTERFACE FOR FEATURE STATE
5
STATE AND REDUCER
CREATING AN INITIAL STATE
SETTING UP BASIC REDUCER
* Here Project is class of type project
NG-RX
import * as fromFeatureA from ‘./featureA.reducer';
export interface AppState {
featureA: fromFeatureA.FeatureAState,
featureB: fromFeatureB.FeatureBState
}
export const reducers: ActionReducerMap<AppState> = {
featureA: fromFeatureA.FeatureAReducer,
featureB: fromFeatureB.FeatureBReducer
}
IMPORTING EVERYTHING FROM FEATURE
6
STORE AND MODULE
MERGING FEATURE STATE IN APP STATE
MERGING FEATURE REDUCER IN APP REDUCER
import { StoreModule } from ‘@ngrx/store’;
import { NgNodule } from '@angular/core';
import { reducers } from ‘.’;
@NgModule({
imports: [StoreModule.forRoot(reducers)]
})
export class StateModule {}
IMPORTING APP REDUCER IN MODULE
IMPORT STORE MODULE AND PASS REDUCERS
import { NgNodule } from '@angular/core';
import { StateModule } from ‘./state.module’;
@NgModule({
imports: [StateModule]
})
export class AppModule {}
IMPORT STATE MODULE IN APP MODULE
NG-RX
import { FeatureAState } from ‘./redux/featureA.reducer’;
constructor(
private store: Store<FeatureAState>
){
this.projects$ = store.pipe(
select(‘featureA’),
map((featureAState: FeatureAState) =>
featureAState.projects)
)
}
7
ACCESSING STORE IN COMPONENT
IMPORT FEATURE STATE
INTERFACE
INJECTING STORE AS SERVICE
SELECTING FIELD FROM FEATURE
STATE
NG-RX
import { StoreModule } from ‘@ngrx/store’;
import { StoreDevToolsModule } from ‘@ngrx/store-devtools';
import { NgNodule } from '@angular/core';
import { reducers } from ‘.’;
@NgModule({
imports: [StoreModule.forRoot(reducers),
StoreDevtoolsModule.instrument({ maxAge: 10 })]
})
export class StateModule {}
8
REDUX DEVTOOLS
IMPORT STORE DEV TOOLS MODULE
NG-RX 9
STRONGLY TYPED ACTIONS
export enum FeatureAActionTypes {
ProjectFetched = '[FeatureA] Fetch’,
ProjectSelected = '[FeatureA] Selected’,
}
import { Action } from '@ngrx/store';
export class SelectProject implements Action {
readonly type = FeatureAActionTypes.ProjectSelected;
constructor(private payload: Project) {}
}
export class FetchProject implements Action {
readonly type = FeatureAActionTypes.ProjectFetched;
}
export type FeatureAAction = SelectProject
| FetchProject
CREATING ENUM FOR ALL ACTIONS
CREATING TYPE OF ACTION WITHOUT PAYLOAD
CREATING TYPE OF ACTION WITH PAYLOAD
EXPORTING ALL ACTIONS AS TYPE
NG-RX 10
MODIFY REDUCER TO USE NEW TYPED ACTIONS
import { FeatureAActionTypes } from ‘./featureA.actions’;
export function featureAReducer(
state = initialFeatureAState, action): FeatureAState{
switch(action.type) {
case FeatureAActionTypes.ProjectSelected:
return {
selectedProjectId: action.payload,
projects: state.projects
}
default:
return state;
}
}
)
IMPORT ACTION ENUM
MAPPING CASES WITH NEW ENUMS
NG-RX 11
COLLECTION MANAGEMENT
export interface FeatureAState extends EntityState<Project> {
selectedProjectId: string | null;
}
export interface FeatureAState {
projects: Project[],
selectedProjectId: string | null;
}
*OLD STATE AS FROM PREVIOUS SLIDE
CHANGING STATE AS ENTITY STATE
export interface EntityState<T> {
ids: string[] | number[];
entities: Dictionary<T>;
}
export const adapter: EntityAdapter<Project> = createEntityAdapter<Project>();
export const initialFeatureAState: FeatureAState = {
projects: initialProjects,
selectedProjectId: null
}
*OLD INITIAL STATE
export const initialState: ProjectsState = adapter.getInitialState({
selectedProjectId: null
}) PULLING INITIAL STATE OUT OF ADAPTER
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
NG-RX 12
BENEFITS OF ENTITY COLLECTION
export function featureAReducer(
state = initialFeatureAState, action): featureAState {
switch (action.type) {
case FeatureAActionTypes.ProjectSelected:
return Object.assign({}, state, { selectedProjectId: action.payload });
case FeatureAActionTypes.ProjectFetched:
return adapter.addMany(action.payload, state);
case FeatureAActionTypes.AddProject:
return adapter.addOne(action.payload, state);
case FeatureAActionTypes.UpdateProject:
return adapter.updateOne(action.payload, state);
case FeatureAActionTypes.DeleteProject:
return adapter.removeOne(action.payload, state);
default:
return state;
}
}
NG-RX
ACCESSING ENTITY COLLECTION IN COMPONENT
constructor(
private store: Store<FeatureAState>
){
this.projects$ = store.pipe(
select(‘featureA’),
map((featureAState: FeatureAState) =>
featureAState.projects)
)
}
constructor(
private store: Store<FeatureAState>
){
this.projects$ = store.pipe(
select(‘featureA'),
map(data => data.entities),
map(data => Object.keys(data).map(k => data[k]))
)
}
*OLD WAY ENTITY COLLECTION IN REDUX DEV TOOLS
NEW WAY (ITS BIT COMPLICATED BUT ONLY IN THIS SLIDE)
13
NG-RX
SELECTORS TO MAKE LIFE EASIER
export const getSelectedProjectID = (state: FeatureAState) => state.selectedProjectId;
LOW LEVEL SELECTOR
const { selectIds, selectEntities, selectAll } = adapter.getSelectors();
export const selectProjectIds = selectIds;
export const selectProjectEntities = selectEntities;
export const selectAllProjects = selectAll;
ADAPTER SELECTORS
import { createFeatureSelector, createSelector } from '@ngrx/store'
export const selectFeatureAState
= createFeatureSelector<FeatureAState>(‘featureA');
export const selectProjectIds = createSelector(
selectProjectsState,
fromFeatureA.selectProjectIds
);
export const selectProjectEntities = createSelector(
selectProjectsState,
fromFeatureA.selectProjectEntities
);
export const selectAllProjects = createSelector(
selectProjectsState,
fromFeatureA.selectAllProjects
);
14
NG-RX
ACCESSING STATE BY SELECTOR IN COMPONENT
constructor(
...
this.projects$ = store.pipe(
select(selectAllProjects)
);
constructor(
private store: Store<FeatureAState>
){
this.projects$ = store.pipe(
select(‘featureA'),
map(data => data.entities),
map(data => Object.keys(data).map(k => data[k]))
)
}
FROM THAT SHIT TO THIS BEAUTY
15
NG-RX
EFFECTS TO HANDLE SIDE EFFECTS (ASYNC)
export enum FeatureAActionTypes {
ProjectFetch = '[FeatureA] Fetch’,
ProjectFetched = '[FeatureA] Fetch Success’,
ProjectSelected = '[FeatureA] Selected’,
}
SPLIT ACTIONS INTO STAGES
@Injectable({providedIn: 'root'})
export class FeatureAEffects {
constructor(
private actions$: Actions,
private projectsService: ProjectsService
) { }
@Effect() fetchProjects$ = this.actions$.pipe(
ofType(FeatureAActionTypes.ProjectFetch),
switchMap((action: FetchProject)) =>
this.projectsService.all()
.pipe(map((res: Project[]) => new ProjectFetched))
)
);
TRIGGER EVENT
COMPLETION EVENT
@NgModule({
imports: [
...
EffectsModule.forRoot([
CustomersEffects,
ProjectsEffects
])
]
})
FINALLY IMPORT IT IN MODULE
16
NG-RX
IMPROVE DATA PERSISTENCE IN EFFECTS WITH NX
17
import { DataPersistence } from '@nrwl/nx';
constructor(
private actions$: Actions,
private dataPersistence: DataPersistence<FeatureAState>,
private projectsService: ProjectsService
) { }
}
@Effect() fetchProjects$ = this.dataPersistence.fetch(FeatureAActionTypes.ProjectFetch, {
run: (action: FetchProject, state: FeatureAState) => {
return this.projectsService.all().pipe(map((res: Project[]) => new ProjectFetched(res)))
},
onError: (action: LoadProjects, error) => {
console.log('ERROR', error);
}
});
@Effect() addProjects$ = this.dataPersistence.pessimisticUpdate(ProjectsActionTypes.addProjects, {
run: () => {},
onError: () => {}
});
@Effect() addProjects$ = this.dataPersistence.optimisticUpdate(ProjectsActionTypes.addProjects, {
run: () => {},
onError: () => {}
});
CLEANING UP EFFECTS WITH DATA
PERSISTENCE
PESSIMISTIC UPDATE
OPTIMISTIC UPDATE
https://nrwl.io/nx/guide-data-persistence
NG-RX
HANDLING RELATIONAL MODELS
18
export const selectFeatureAState
= createFeatureSelector<FeatureAState>(‘featureA');
export const selectCurrentProjectId = createSelector(
selectFeatureAState,
fromFeatureA.getSelectedProjectId
);
export const getSelectedProjectID = (state: FeatureAState) => state.selectedProjectId;
export const selectCurrentProject = createSelector(
selectProjectEntities,
selectCurrentProjectId,
(projectEntities, projectId) =>
return projectId ? projectEntities[projectId] : null ;
)
const { selectIds, selectEntities, selectAll } = adapter.getSelectors();
export const selectProjectEntities = selectEntities;
export const selectCustomrsProjects = createSelector(
selectAllCustomers,
selectAllProjects,
(customers, projects) => {}
)
COMPOSING SELECTORS FROM SAME
MODEL
COMPOSING SELECTORS FROM DIFFERENT
MODEL
NG-RX
QUESTIONS

More Related Content

What's hot

Introduction to react_js
Introduction to react_jsIntroduction to react_js
Introduction to react_jsMicroPyramid .
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux IntroductionNikolaus Graf
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners Varun Raj
 
An introduction to React.js
An introduction to React.jsAn introduction to React.js
An introduction to React.jsEmanuele DelBono
 
Important React Hooks
Important React HooksImportant React Hooks
Important React HooksKnoldus Inc.
 
Understanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree TechnologiesUnderstanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree TechnologiesWalking Tree Technologies
 
React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?Fibonalabs
 

What's hot (20)

Introduction to react_js
Introduction to react_jsIntroduction to react_js
Introduction to react_js
 
Intro to React
Intro to ReactIntro to React
Intro to React
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
 
Its time to React.js
Its time to React.jsIts time to React.js
Its time to React.js
 
React workshop
React workshopReact workshop
React workshop
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
Redux workshop
Redux workshopRedux workshop
Redux workshop
 
Reactjs
ReactjsReactjs
Reactjs
 
Introduction to React JS for beginners
Introduction to React JS for beginners Introduction to React JS for beginners
Introduction to React JS for beginners
 
Introduction to React JS
Introduction to React JSIntroduction to React JS
Introduction to React JS
 
React JS part 1
React JS part 1React JS part 1
React JS part 1
 
An introduction to React.js
An introduction to React.jsAn introduction to React.js
An introduction to React.js
 
React JS - Introduction
React JS - IntroductionReact JS - Introduction
React JS - Introduction
 
Important React Hooks
Important React HooksImportant React Hooks
Important React Hooks
 
React js
React jsReact js
React js
 
React hooks
React hooksReact hooks
React hooks
 
React / Redux Architectures
React / Redux ArchitecturesReact / Redux Architectures
React / Redux Architectures
 
React and redux
React and reduxReact and redux
React and redux
 
Understanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree TechnologiesUnderstanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree Technologies
 
React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?React Class Components vs Functional Components: Which is Better?
React Class Components vs Functional Components: Which is Better?
 

Similar to Ngrx

Evan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-reduxEvan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-reduxEvan Schultz
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.AngularEvan Schultz
 
[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법Jeado Ko
 
Introducing Vuex in your project
Introducing Vuex in your projectIntroducing Vuex in your project
Introducing Vuex in your projectDenny Biasiolli
 
State manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexState manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexCommit University
 
Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Nir Kaufman
 
Using React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsUsing React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsMihail Gaberov
 
Recoil at Codete Webinars #3
Recoil at Codete Webinars #3Recoil at Codete Webinars #3
Recoil at Codete Webinars #3Mateusz Bryła
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsEvangelia Mitsopoulou
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Ahmed Moawad
 
Angular js 2.0, ng poznań 20.11
Angular js 2.0, ng poznań 20.11Angular js 2.0, ng poznań 20.11
Angular js 2.0, ng poznań 20.11Kamil Augustynowicz
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 DreamLab
 
Angular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app exampleAngular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app exampleAlexey Frolov
 
End to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaEnd to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaBabacar NIANG
 
angular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfangular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfNuttavutThongjor1
 
Architecture for scalable Angular applications (with introduction and extende...
Architecture for scalable Angular applications (with introduction and extende...Architecture for scalable Angular applications (with introduction and extende...
Architecture for scalable Angular applications (with introduction and extende...Paweł Żurowski
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Ontico
 

Similar to Ngrx (20)

Evan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-reduxEvan Schultz - Angular Camp - ng2-redux
Evan Schultz - Angular Camp - ng2-redux
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.Angular
 
Side effects-con-redux
Side effects-con-reduxSide effects-con-redux
Side effects-con-redux
 
React redux
React reduxReact redux
React redux
 
Reactive Angular 2
Reactive Angular 2Reactive Angular 2
Reactive Angular 2
 
[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법
 
Introducing Vuex in your project
Introducing Vuex in your projectIntroducing Vuex in your project
Introducing Vuex in your project
 
State manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexState manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to Vuex
 
Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016
 
Using React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsUsing React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIs
 
Recoil at Codete Webinars #3
Recoil at Codete Webinars #3Recoil at Codete Webinars #3
Recoil at Codete Webinars #3
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applications
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2
 
Angular js 2.0, ng poznań 20.11
Angular js 2.0, ng poznań 20.11Angular js 2.0, ng poznań 20.11
Angular js 2.0, ng poznań 20.11
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3
 
Angular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app exampleAngular2: Quick overview with 2do app example
Angular2: Quick overview with 2do app example
 
End to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux SagaEnd to end todo list app with NestJs - Angular - Redux & Redux Saga
End to end todo list app with NestJs - Angular - Redux & Redux Saga
 
angular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfangular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdf
 
Architecture for scalable Angular applications (with introduction and extende...
Architecture for scalable Angular applications (with introduction and extende...Architecture for scalable Angular applications (with introduction and extende...
Architecture for scalable Angular applications (with introduction and extende...
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
 

Recently uploaded

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfOverkill Security
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024The Digital Insurer
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...apidays
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 

Recently uploaded (20)

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 

Ngrx

  • 2. ABOUT ME SUWIGYA RATHORE ▸ Front end developer with 7+ years of experience ▸ Working for Non Dutch from Sep 2018 ▸ Working on Angular from starting almost 2+ years ▸ Have experience of 2 years with largest customer facing Angular website Air France & KLM (probably Air Kenya, Joon, Transavia etc.) ▸ Working with dffrntmedia on Earthtoday.com ▸ Loves to travel ▸ Read and experiment about latest technologies ▸ Loves to do binge watching on Netflix
  • 3. RULE 4: REDUX SHOULD THE MEANS OF ACHIEVING A GOAL, NOT THE GOAL RULE 5: ALWAYS TREAT ROUTER AS THE SOURCE OF TRUTH Victor Savkin NG-RX https://blog.nrwl.io/managing-state-in-angular-applications-22b75ef5625f 3 GOLDEN RULES
  • 4. TEXT AGENDA ▸ State and reducer setup ▸ NG-RX Store setup @ngrx/store ▸ Accessing State in Component ▸ Redux devtools with angular @ngrx/store-devtools ▸ Collection management @ngrx/entity ▸ Dispatching strongly typed actions ▸ State selectors ▸ Async operations with effects @ngrx/effects ▸ Improve server communication with NX data persistence layer @nrwl/nx ▸ Connect Related data models ▸ Folder structure in project & demo 4
  • 5. NG-RX export interface FeatureAState { projects: Project[], selectedProjectId: string | null; } export const initialFeatureAState: FeatureAState = { projects: initialProjects, selectedProjectId: null } export function featureAReducer( state = initialFeatureAState, action): FeatureAState{ switch(action.type) { default: return state; } } ) CREATING INTERFACE FOR FEATURE STATE 5 STATE AND REDUCER CREATING AN INITIAL STATE SETTING UP BASIC REDUCER * Here Project is class of type project
  • 6. NG-RX import * as fromFeatureA from ‘./featureA.reducer'; export interface AppState { featureA: fromFeatureA.FeatureAState, featureB: fromFeatureB.FeatureBState } export const reducers: ActionReducerMap<AppState> = { featureA: fromFeatureA.FeatureAReducer, featureB: fromFeatureB.FeatureBReducer } IMPORTING EVERYTHING FROM FEATURE 6 STORE AND MODULE MERGING FEATURE STATE IN APP STATE MERGING FEATURE REDUCER IN APP REDUCER import { StoreModule } from ‘@ngrx/store’; import { NgNodule } from '@angular/core'; import { reducers } from ‘.’; @NgModule({ imports: [StoreModule.forRoot(reducers)] }) export class StateModule {} IMPORTING APP REDUCER IN MODULE IMPORT STORE MODULE AND PASS REDUCERS import { NgNodule } from '@angular/core'; import { StateModule } from ‘./state.module’; @NgModule({ imports: [StateModule] }) export class AppModule {} IMPORT STATE MODULE IN APP MODULE
  • 7. NG-RX import { FeatureAState } from ‘./redux/featureA.reducer’; constructor( private store: Store<FeatureAState> ){ this.projects$ = store.pipe( select(‘featureA’), map((featureAState: FeatureAState) => featureAState.projects) ) } 7 ACCESSING STORE IN COMPONENT IMPORT FEATURE STATE INTERFACE INJECTING STORE AS SERVICE SELECTING FIELD FROM FEATURE STATE
  • 8. NG-RX import { StoreModule } from ‘@ngrx/store’; import { StoreDevToolsModule } from ‘@ngrx/store-devtools'; import { NgNodule } from '@angular/core'; import { reducers } from ‘.’; @NgModule({ imports: [StoreModule.forRoot(reducers), StoreDevtoolsModule.instrument({ maxAge: 10 })] }) export class StateModule {} 8 REDUX DEVTOOLS IMPORT STORE DEV TOOLS MODULE
  • 9. NG-RX 9 STRONGLY TYPED ACTIONS export enum FeatureAActionTypes { ProjectFetched = '[FeatureA] Fetch’, ProjectSelected = '[FeatureA] Selected’, } import { Action } from '@ngrx/store'; export class SelectProject implements Action { readonly type = FeatureAActionTypes.ProjectSelected; constructor(private payload: Project) {} } export class FetchProject implements Action { readonly type = FeatureAActionTypes.ProjectFetched; } export type FeatureAAction = SelectProject | FetchProject CREATING ENUM FOR ALL ACTIONS CREATING TYPE OF ACTION WITHOUT PAYLOAD CREATING TYPE OF ACTION WITH PAYLOAD EXPORTING ALL ACTIONS AS TYPE
  • 10. NG-RX 10 MODIFY REDUCER TO USE NEW TYPED ACTIONS import { FeatureAActionTypes } from ‘./featureA.actions’; export function featureAReducer( state = initialFeatureAState, action): FeatureAState{ switch(action.type) { case FeatureAActionTypes.ProjectSelected: return { selectedProjectId: action.payload, projects: state.projects } default: return state; } } ) IMPORT ACTION ENUM MAPPING CASES WITH NEW ENUMS
  • 11. NG-RX 11 COLLECTION MANAGEMENT export interface FeatureAState extends EntityState<Project> { selectedProjectId: string | null; } export interface FeatureAState { projects: Project[], selectedProjectId: string | null; } *OLD STATE AS FROM PREVIOUS SLIDE CHANGING STATE AS ENTITY STATE export interface EntityState<T> { ids: string[] | number[]; entities: Dictionary<T>; } export const adapter: EntityAdapter<Project> = createEntityAdapter<Project>(); export const initialFeatureAState: FeatureAState = { projects: initialProjects, selectedProjectId: null } *OLD INITIAL STATE export const initialState: ProjectsState = adapter.getInitialState({ selectedProjectId: null }) PULLING INITIAL STATE OUT OF ADAPTER import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
  • 12. NG-RX 12 BENEFITS OF ENTITY COLLECTION export function featureAReducer( state = initialFeatureAState, action): featureAState { switch (action.type) { case FeatureAActionTypes.ProjectSelected: return Object.assign({}, state, { selectedProjectId: action.payload }); case FeatureAActionTypes.ProjectFetched: return adapter.addMany(action.payload, state); case FeatureAActionTypes.AddProject: return adapter.addOne(action.payload, state); case FeatureAActionTypes.UpdateProject: return adapter.updateOne(action.payload, state); case FeatureAActionTypes.DeleteProject: return adapter.removeOne(action.payload, state); default: return state; } }
  • 13. NG-RX ACCESSING ENTITY COLLECTION IN COMPONENT constructor( private store: Store<FeatureAState> ){ this.projects$ = store.pipe( select(‘featureA’), map((featureAState: FeatureAState) => featureAState.projects) ) } constructor( private store: Store<FeatureAState> ){ this.projects$ = store.pipe( select(‘featureA'), map(data => data.entities), map(data => Object.keys(data).map(k => data[k])) ) } *OLD WAY ENTITY COLLECTION IN REDUX DEV TOOLS NEW WAY (ITS BIT COMPLICATED BUT ONLY IN THIS SLIDE) 13
  • 14. NG-RX SELECTORS TO MAKE LIFE EASIER export const getSelectedProjectID = (state: FeatureAState) => state.selectedProjectId; LOW LEVEL SELECTOR const { selectIds, selectEntities, selectAll } = adapter.getSelectors(); export const selectProjectIds = selectIds; export const selectProjectEntities = selectEntities; export const selectAllProjects = selectAll; ADAPTER SELECTORS import { createFeatureSelector, createSelector } from '@ngrx/store' export const selectFeatureAState = createFeatureSelector<FeatureAState>(‘featureA'); export const selectProjectIds = createSelector( selectProjectsState, fromFeatureA.selectProjectIds ); export const selectProjectEntities = createSelector( selectProjectsState, fromFeatureA.selectProjectEntities ); export const selectAllProjects = createSelector( selectProjectsState, fromFeatureA.selectAllProjects ); 14
  • 15. NG-RX ACCESSING STATE BY SELECTOR IN COMPONENT constructor( ... this.projects$ = store.pipe( select(selectAllProjects) ); constructor( private store: Store<FeatureAState> ){ this.projects$ = store.pipe( select(‘featureA'), map(data => data.entities), map(data => Object.keys(data).map(k => data[k])) ) } FROM THAT SHIT TO THIS BEAUTY 15
  • 16. NG-RX EFFECTS TO HANDLE SIDE EFFECTS (ASYNC) export enum FeatureAActionTypes { ProjectFetch = '[FeatureA] Fetch’, ProjectFetched = '[FeatureA] Fetch Success’, ProjectSelected = '[FeatureA] Selected’, } SPLIT ACTIONS INTO STAGES @Injectable({providedIn: 'root'}) export class FeatureAEffects { constructor( private actions$: Actions, private projectsService: ProjectsService ) { } @Effect() fetchProjects$ = this.actions$.pipe( ofType(FeatureAActionTypes.ProjectFetch), switchMap((action: FetchProject)) => this.projectsService.all() .pipe(map((res: Project[]) => new ProjectFetched)) ) ); TRIGGER EVENT COMPLETION EVENT @NgModule({ imports: [ ... EffectsModule.forRoot([ CustomersEffects, ProjectsEffects ]) ] }) FINALLY IMPORT IT IN MODULE 16
  • 17. NG-RX IMPROVE DATA PERSISTENCE IN EFFECTS WITH NX 17 import { DataPersistence } from '@nrwl/nx'; constructor( private actions$: Actions, private dataPersistence: DataPersistence<FeatureAState>, private projectsService: ProjectsService ) { } } @Effect() fetchProjects$ = this.dataPersistence.fetch(FeatureAActionTypes.ProjectFetch, { run: (action: FetchProject, state: FeatureAState) => { return this.projectsService.all().pipe(map((res: Project[]) => new ProjectFetched(res))) }, onError: (action: LoadProjects, error) => { console.log('ERROR', error); } }); @Effect() addProjects$ = this.dataPersistence.pessimisticUpdate(ProjectsActionTypes.addProjects, { run: () => {}, onError: () => {} }); @Effect() addProjects$ = this.dataPersistence.optimisticUpdate(ProjectsActionTypes.addProjects, { run: () => {}, onError: () => {} }); CLEANING UP EFFECTS WITH DATA PERSISTENCE PESSIMISTIC UPDATE OPTIMISTIC UPDATE https://nrwl.io/nx/guide-data-persistence
  • 18. NG-RX HANDLING RELATIONAL MODELS 18 export const selectFeatureAState = createFeatureSelector<FeatureAState>(‘featureA'); export const selectCurrentProjectId = createSelector( selectFeatureAState, fromFeatureA.getSelectedProjectId ); export const getSelectedProjectID = (state: FeatureAState) => state.selectedProjectId; export const selectCurrentProject = createSelector( selectProjectEntities, selectCurrentProjectId, (projectEntities, projectId) => return projectId ? projectEntities[projectId] : null ; ) const { selectIds, selectEntities, selectAll } = adapter.getSelectors(); export const selectProjectEntities = selectEntities; export const selectCustomrsProjects = createSelector( selectAllCustomers, selectAllProjects, (customers, projects) => {} ) COMPOSING SELECTORS FROM SAME MODEL COMPOSING SELECTORS FROM DIFFERENT MODEL