Jump into concepts and practice - no test required
or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
NgRx Store Concept
📖 Scenario: You are building a simple Angular app to manage a list of favorite fruits. You want to use NgRx store to keep the list in a central place so different parts of your app can access and update it easily.
🎯 Goal: Create a basic NgRx store setup to hold a list of fruits, add a configuration for the initial state, write a reducer to handle adding a fruit, and complete the store module setup in your Angular app.
📋 What You'll Learn
Create an initial state object with a fruits array
Add a configuration variable for the initial state
Write a reducer function to handle adding a fruit to the fruits array
Complete the NgRx StoreModule setup in the Angular app module
💡 Why This Matters
🌍 Real World
NgRx store helps manage app state in large Angular apps, making data flow predictable and easier to debug.
💼 Career
Understanding NgRx store is important for Angular developers working on scalable, maintainable applications with complex state.
Progress0 / 4 steps
1
Create initial state
Create a constant called initialState with an object that has a property fruits set to an empty array.
Angular
Hint
Think of initialState as the starting point for your fruit list in the store.
2
Add initial state configuration
Create a constant called fruitFeatureKey and set it to the string 'fruit' to identify this feature in the store.
Angular
Hint
This key helps NgRx know which part of the store holds your fruit data.
3
Write reducer to add fruit
Write a reducer function called fruitReducer that takes state and action parameters. Use a switch on action.type. When the type is 'addFruit', return a new state with the fruits array including the new fruit from action.payload. For default, return the current state.
Angular
Hint
The reducer updates the state based on the action type. Here, it adds a new fruit to the list.
4
Complete StoreModule setup
In your Angular module file, import StoreModule from @ngrx/store. Then add StoreModule.forRoot({ [fruitFeatureKey]: fruitReducer }) to the imports array of your @NgModule decorator.
Angular
Hint
This step connects your reducer to the Angular app so the store works globally.
Practice
(1/5)
1. What is the primary purpose of the NgRx Store in an Angular application?
easy
A. To style components with CSS dynamically
B. To handle HTTP requests and responses automatically
C. To keep all application data in one central place for easy access and updates
D. To manage routing between different pages
Solution
Step 1: Understand NgRx Store role
The NgRx Store is designed to hold the application state in one place.
Step 2: Compare with other options
Options B, C, and D describe other Angular features, not the store's purpose.
Final Answer:
To keep all application data in one central place for easy access and updates -> Option C
Quick Check:
NgRx Store = Central app data storage [OK]
Hint: NgRx Store = single source of truth for app data [OK]
Common Mistakes:
Confusing store with routing or HTTP services
Thinking store manages styles or UI directly
2. Which of the following is the correct way to dispatch an action named loadItems using NgRx Store in a component?
easy
A. this.store.call(loadItems);
B. this.store.emit(loadItems);
C. store.dispatch = loadItems();
D. this.store.dispatch(loadItems());
Solution
Step 1: Recall NgRx dispatch syntax
Actions are dispatched by calling this.store.dispatch(action()).
Step 2: Check other options for syntax errors
Options A, B, and C use incorrect methods or assignment instead of dispatch call.
What will be the state after dispatching { type: 'increment' } twice starting from initial state?
medium
A. { count: 0 }
B. { count: 2 }
C. { count: 1 }
D. { count: -2 }
Solution
Step 1: Analyze reducer behavior for 'increment'
Each 'increment' action adds 1 to the current count.
Step 2: Apply two increments starting from 0
0 + 1 = 1 after first increment, then 1 + 1 = 2 after second increment.
Final Answer:
{ count: 2 } -> Option B
Quick Check:
Two increments = count 2 [OK]
Hint: Add 1 per 'increment' action to count [OK]
Common Mistakes:
Counting only one increment
Confusing decrement with increment
4. Identify the error in this NgRx reducer code:
function todoReducer(state = [], action) {
if (action.type === 'add') {
state.push(action.payload);
return state;
}
return state;
}
medium
A. Mutating state directly instead of returning a new state
B. Missing default case in reducer
C. Incorrect action type string
D. Reducer should not return state
Solution
Step 1: Check state mutation
The reducer uses state.push(), which changes the original array directly.
Step 2: Understand NgRx immutability rule
Reducers must return new state objects without mutating the old state.
Final Answer:
Mutating state directly instead of returning a new state -> Option A
Quick Check:
Reducers must be pure and immutable [OK]
Hint: Never mutate state; always return new object/array [OK]
Common Mistakes:
Using push instead of spread operator
Ignoring immutability in reducers
5. You want to create a feature state slice for user profiles using NgRx. Which combination correctly sets up the feature state and selector?
1. Define interface UserProfileState { name: string; age: number; } 2. Create reducer userProfileReducer 3. Register feature state with key 'userProfile' 4. Select user name from store
Which code snippet correctly selects the user name?
hard
A. const selectUserProfile = createFeatureSelector<UserProfileState>('userProfile');
const selectUserName = createSelector(selectUserProfile, state => state.name);
B. const selectUserName = createSelector('userProfile', state => state.name);
C. const selectUserProfile = createSelector('userProfile');
const selectUserName = state => state.name;
D. const selectUserName = createFeatureSelector<UserProfileState>('userProfile').pipe(map(state => state.name));
Solution
Step 1: Understand feature selector usage
Use createFeatureSelector with the feature key to get the feature state.
Step 2: Create selector for user name
Use createSelector with the feature selector and a projector function to select the name.
Final Answer:
const selectUserProfile = createFeatureSelector<UserProfileState>('userProfile');
const selectUserName = createSelector(selectUserProfile, state => state.name); -> Option A