Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
NgRx Feature Creator
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Marko Stanimirović
September 02, 2022
Programming
240
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
NgRx Feature Creator
Marko Stanimirović
September 02, 2022
More Decks by Marko Stanimirović
See All by Marko Stanimirović
[NG India] Event-Based State Management with NgRx SignalStore
markostanimirovic
1
300
NgRx - Core Principles & New Features
markostanimirovic
0
650
Dependency Injection in Angular
markostanimirovic
0
240
NgRx Action Group Creator
markostanimirovic
1
800
NgRx Tips for Future-Proof Angular Apps
markostanimirovic
0
270
NgRx Store - Tips For Better Code Hygiene
markostanimirovic
1
190
Other Decks in Programming
See All in Programming
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
160
Creating Composable Callables in Contemporary C++
rollbear
0
130
Oxcを導入して開発体験が向上した話
yug1224
4
310
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
320
Lessons from Spec-Driven Development
simas
PRO
0
190
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
490
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
240
AI時代のUIはどこへ行く?その2!
yusukebe
21
7.2k
「エンジニアインターン、どうやって取った?」準備のリアルを語るLT会 Progate BAR
akiomatic
0
130
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
110
Signal Forms: Beyond the Basics @ngBaguette 2026 in Paris
manfredsteyer
PRO
0
250
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
340
Featured
See All Featured
Why Our Code Smells
bkeepers
PRO
340
58k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
840
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
370
Measuring & Analyzing Core Web Vitals
bluesmoon
9
860
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
430
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
250
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Making Projects Easy
brettharned
120
6.7k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Prompt Engineering for Job Search
mfonobong
0
340
The Language of Interfaces
destraynor
162
27k
Transcript
NgRx Feature Creator Marko Stanimirović
Marko Stanimirović @MarkoStDev ★ Sr. Frontend Engineer at JobCloud ★
NgRx Team Member ★ Angular Belgrade Organizer ★ Hobby Musician ★ M.Sc. in Software Engineering
What is NgRx Feature?
Reducer
Reducer Feature Name
Reducer Feature Name Selectors
Reducer Feature Name Selectors NgRx Feature
Creating NgRx Feature
export interface State { songs: Song[]; activeSongId: number | null;
isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; songs.reducer.ts
import { createReducer } from '@ngrx/store'; export interface State {
songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( ); songs.reducer.ts
import { createReducer } from '@ngrx/store'; export interface State {
songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( initialState, ); songs.reducer.ts
import { createReducer, on } from '@ngrx/store'; export interface State
{ songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( initialState, on( SongsApiActions.songsLoadedSuccess, (state, { songs }) => ({ ==.state, songs, isLoading: false, }) ), on(** **. */) ); songs.reducer.ts
import { createReducer, on } from '@ngrx/store'; export interface State
{ songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( initialState, on( SongsApiActions.songsLoadedSuccess, (state, { songs }) => ({ ==.state, songs, isLoading: false, }) ), on(** **. */) ); export const featureName = 'songs'; songs.reducer.ts
songs.module.ts import { StoreModule } from '@ngrx/store'; import * as
fromSongs from './songs.reducer'; @NgModule({ imports: [ StoreModule.forFeature( fromSongs.featureName, fromSongs.reducer ), ], }) export class SongsModule {} import { createReducer, on } from '@ngrx/store'; export interface State { songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( initialState, on( SongsApiActions.songsLoadedSuccess, (state, { songs }) => ({ ==.state, songs, isLoading: false, }) ), on(** **. */) ); export const featureName = 'songs'; songs.reducer.ts
import { createReducer, on } from '@ngrx/store'; export interface State
{ songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( initialState, on( SongsApiActions.songsLoadedSuccess, (state, { songs }) => ({ ==.state, songs, isLoading: false, }) ), on(** **. */) ); export const featureName = 'songs'; songs.reducer.ts songs.selectors.ts
import { createReducer, on } from '@ngrx/store'; export interface State
{ songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( initialState, on( SongsApiActions.songsLoadedSuccess, (state, { songs }) => ({ ==.state, songs, isLoading: false, }) ), on(** **. */) ); export const featureName = 'songs'; songs.reducer.ts import { createFeatureSelector, } from '@ngrx/store'; import * as fromSongs from './songs.reducer'; export const selectSongsState = createFeatureSelector<fromSongs.State>(fromSongs.featureName); songs.selectors.ts
import { createReducer, on } from '@ngrx/store'; export interface State
{ songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const reducer = createReducer( initialState, on( SongsApiActions.songsLoadedSuccess, (state, { songs }) => ({ ==.state, songs, isLoading: false, }) ), on(** **. */) ); export const featureName = 'songs'; songs.reducer.ts import { createFeatureSelector, createSelector, } from '@ngrx/store'; import * as fromSongs from './songs.reducer'; export const selectSongsState = createFeatureSelector<fromSongs.State>(fromSongs.featureName); export const selectSongs = createSelector( selectSongsState, (state) => state.songs ); export const selectActiveSongId = createSelector( selectSongsState, (state) => state.activeSongId ); export const selectIsLoading = createSelector( selectSongsState, (state) => state.isLoading ); songs.selectors.ts
createFeature
songs.reducer.ts import { createFeature } from '@ngrx/store'; export interface State
{ songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const songsFeature = createFeature({ });
songs.reducer.ts import { createFeature } from '@ngrx/store'; export interface State
{ songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const songsFeature = createFeature({ name: 'songs' });
songs.reducer.ts import { createFeature, createReducer, on } from '@ngrx/store'; export
interface State { songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const songsFeature = createFeature({ name: 'songs', reducer: createReducer( initialState, on(** **. */), on(** **. */) ), });
songs.reducer.ts import { createFeature, createReducer, on } from '@ngrx/store'; export
interface State { songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const songsFeature = createFeature({ name: 'songs', reducer: createReducer( initialState, on(** **. */), on(** **. */) ), }); const { name, =/ feature name reducer, =/ feature reducer selectSongsState, =/ feature selector selectSongs, =/ selector for `songs` property selectActiveSongId, =/ selector for `activeSongId` property selectIsLoading, =/ selector for `isLoading` property } = songsFeature;
songs.reducer.ts import { createFeature, createReducer, on } from '@ngrx/store'; export
interface State { songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const songsFeature = createFeature({ name: 'songs', reducer: createReducer( initialState, on(** **. */), on(** **. */) ), }); const { name, =/ feature name reducer, =/ feature reducer selectSongsState, =/ feature selector selectSongs, =/ selector for `songs` property selectActiveSongId, =/ selector for `activeSongId` property selectIsLoading, =/ selector for `isLoading` property } = songsFeature; songs.selectors.ts import { createSelector } from '@ngrx/store'; import { songsFeature } from './songs.reducer'; export const selectActiveSong = createSelector( songsFeature.selectSongs, songsFeature.selectActiveSongId, (songs, activeSongId) => songs.find((song) => song.id === activeSongId) );
songs.reducer.ts import { createFeature, createReducer, on } from '@ngrx/store'; export
interface State { songs: Song[]; activeSongId: number | null; isLoading: boolean; } const initialState: State = { songs: [], activeSongId: null, isLoading: false, }; export const songsFeature = createFeature({ name: 'songs', reducer: createReducer( initialState, on(** **. */), on(** **. */) ), }); const { name, =/ feature name reducer, =/ feature reducer selectSongsState, =/ feature selector selectSongs, =/ selector for `songs` property selectActiveSongId, =/ selector for `activeSongId` property selectIsLoading, =/ selector for `isLoading` property } = songsFeature; songs.module.ts import { StoreModule } from '@ngrx/store'; import { songsFeature } from './songs.reducer'; @NgModule({ imports: [ StoreModule.forFeature(songsFeature), ], }) export class SongsModule {} songs.selectors.ts import { createSelector } from '@ngrx/store'; import { songsFeature } from './songs.reducer'; export const selectActiveSong = createSelector( songsFeature.selectSongs, songsFeature.selectActiveSongId, (songs, activeSongId) => songs.find((song) => song.id === activeSongId) );
Marko Stanimirović @MarkoStDev Thank You!