Bird
Raised Fist0
Angularframework~30 mins

NgRx store concept in Angular - Mini Project: Build & Apply

Choose your learning style10 modes available

Start learning this pattern below

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

  1. Step 1: Understand NgRx Store role

    The NgRx Store is designed to hold the application state in one place.
  2. Step 2: Compare with other options

    Options B, C, and D describe other Angular features, not the store's purpose.
  3. Final Answer:

    To keep all application data in one central place for easy access and updates -> Option C
  4. 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

  1. Step 1: Recall NgRx dispatch syntax

    Actions are dispatched by calling this.store.dispatch(action()).
  2. Step 2: Check other options for syntax errors

    Options A, B, and C use incorrect methods or assignment instead of dispatch call.
  3. Final Answer:

    this.store.dispatch(loadItems()); -> Option D
  4. Quick Check:

    Dispatch action = this.store.dispatch(action()) [OK]
Hint: Dispatch actions with this.store.dispatch(action()) [OK]
Common Mistakes:
  • Using emit or call instead of dispatch
  • Assigning dispatch instead of calling it
3. Given this reducer snippet:
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
  switch(action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

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

  1. Step 1: Analyze reducer behavior for 'increment'

    Each 'increment' action adds 1 to the current count.
  2. Step 2: Apply two increments starting from 0

    0 + 1 = 1 after first increment, then 1 + 1 = 2 after second increment.
  3. Final Answer:

    { count: 2 } -> Option B
  4. 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

  1. Step 1: Check state mutation

    The reducer uses state.push(), which changes the original array directly.
  2. Step 2: Understand NgRx immutability rule

    Reducers must return new state objects without mutating the old state.
  3. Final Answer:

    Mutating state directly instead of returning a new state -> Option A
  4. 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

  1. Step 1: Understand feature selector usage

    Use createFeatureSelector with the feature key to get the feature state.
  2. Step 2: Create selector for user name

    Use createSelector with the feature selector and a projector function to select the name.
  3. Final Answer:

    const selectUserProfile = createFeatureSelector<UserProfileState>('userProfile'); const selectUserName = createSelector(selectUserProfile, state => state.name); -> Option A
  4. Quick Check:

    Feature selector + createSelector = correct pattern [OK]
Hint: Use createFeatureSelector then createSelector for nested state [OK]
Common Mistakes:
  • Passing string directly to createSelector
  • Using pipe on selector instead of RxJS operators in component