Bird
Raised Fist0
Angularframework~20 mins

Actions and reducers pattern in Angular - Practice Problems & Coding Challenges

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
Challenge - 5 Problems
🎖️
Actions and Reducers Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
component_behavior
intermediate
2:00remaining
What is the output of this reducer function?

Consider this Angular reducer function handling a counter state. What will be the new state after dispatching the action { type: 'increment' } when the current state is { count: 5 }?

Angular
function counterReducer(state = { count: 0 }, action: { type: string }) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const currentState = { count: 5 };
const newState = counterReducer(currentState, { type: 'increment' });
console.log(newState);
Aundefined
B{ count: 5 }
C{ count: 4 }
D{ count: 6 }
Attempts:
2 left
💡 Hint

Think about what the reducer does when it receives the 'increment' action.

📝 Syntax
intermediate
2:00remaining
Which option correctly defines an action creator function in Angular?

Choose the correct syntax for an action creator function that returns an action object with type 'addItem' and a payload containing an item string.

Afunction addItem(item: string) { return { actionType: 'addItem', data: item }; }
Bfunction addItem(item: string) { return { type: 'addItem', payload: item }; }
Cfunction addItem(item: string) { return { type: addItem, payload: item }; }
Dfunction addItem(item: string) { return { type: 'addItem', item }; }
Attempts:
2 left
💡 Hint

Look for the standard keys used in action objects.

🔧 Debug
advanced
2:00remaining
Why does this reducer cause an error?

Examine the reducer code below. Why will it cause an error when dispatched with any action?

Angular
function todoReducer(state = [], action: { type: string, payload?: string }) {
  switch (action.type) {
    case 'add':
      state.push(action.payload);
      return state;
    default:
      return state;
  }
}
AIt does not handle the 'remove' action type.
BIt uses an invalid switch statement syntax.
CIt mutates the state array directly, which is not allowed in reducers.
DIt returns undefined instead of a state object.
Attempts:
2 left
💡 Hint

Reducers should never change the original state directly.

state_output
advanced
2:00remaining
What is the final state after these actions?

Given the reducer and the sequence of dispatched actions below, what is the final state?

Angular
function counterReducer(state = { count: 0 }, action: { type: string }) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      return state;
  }
}

let state = { count: 0 };
state = counterReducer(state, { type: 'increment' });
state = counterReducer(state, { type: 'increment' });
state = counterReducer(state, { type: 'decrement' });
state = counterReducer(state, { type: 'reset' });
state = counterReducer(state, { type: 'increment' });
console.log(state);
A{ count: 1 }
B{ count: 2 }
C{ count: 0 }
D{ count: 3 }
Attempts:
2 left
💡 Hint

Follow each action step by step and update the count.

🧠 Conceptual
expert
2:00remaining
Which statement best describes the role of actions in the reducer pattern?

Choose the most accurate description of what actions do in the actions and reducers pattern in Angular.

AActions describe what happened and carry data to update the state accordingly.
BActions store the entire application state for the reducer to use.
CActions are functions that return the new state after processing.
DActions directly modify the state to reflect user interactions.
Attempts:
2 left
💡 Hint

Think about the purpose of actions as messages.

Practice

(1/5)
1. In Angular's actions and reducers pattern, what is the main role of an action?
easy
A. To describe what happened and carry data about the event
B. To directly update the UI components
C. To store the entire application state
D. To fetch data from the server

Solution

  1. Step 1: Understand the purpose of actions

    Actions are simple objects that describe an event that happened in the app and carry any necessary data.
  2. Step 2: Differentiate from other parts

    Reducers handle state changes, not actions. UI updates and data fetching are separate concerns.
  3. Final Answer:

    To describe what happened and carry data about the event -> Option A
  4. Quick Check:

    Action = event description + data [OK]
Hint: Actions describe events, reducers change state [OK]
Common Mistakes:
  • Confusing actions with reducers
  • Thinking actions update UI directly
  • Assuming actions hold the whole state
2. Which of the following is the correct syntax to define an action using Angular's createAction function?
easy
A. const loadItems = createAction('Load Items', payload);
B. const loadItems = createAction = 'Load Items';
C. const loadItems = actionCreate('Load Items');
D. const loadItems = createAction('Load Items');

Solution

  1. Step 1: Recall createAction syntax

    The correct syntax is calling createAction with a string describing the action type.
  2. Step 2: Check each option

    const loadItems = createAction('Load Items'); matches the correct syntax. const loadItems = createAction = 'Load Items'; uses wrong assignment. const loadItems = actionCreate('Load Items'); uses wrong function name. const loadItems = createAction('Load Items', payload); incorrectly adds a second argument without proper structure.
  3. Final Answer:

    const loadItems = createAction('Load Items'); -> Option D
  4. Quick Check:

    createAction('type') is correct [OK]
Hint: createAction takes a single string type [OK]
Common Mistakes:
  • Using wrong function names
  • Assigning createAction instead of calling it
  • Passing payload directly as second argument
3. Given this reducer snippet, what will be the new state after dispatching { type: 'increment' } if the initial state is { count: 0 }?
function counterReducer(state = { count: 0 }, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}
medium
A. { count: 1 }
B. { count: 0 }
C. { count: -1 }
D. undefined

Solution

  1. Step 1: Identify the action type and initial state

    The action type is 'increment' and initial state has count 0.
  2. Step 2: Follow reducer logic for 'increment'

    The reducer returns a new state with count increased by 1, so count becomes 1.
  3. Final Answer:

    { count: 1 } -> Option A
  4. Quick Check:

    increment adds 1 to count [OK]
Hint: Reducer returns new state based on action type [OK]
Common Mistakes:
  • Returning old state instead of updated
  • Confusing increment with decrement
  • Expecting mutation instead of new object
4. What is wrong with this reducer code snippet?
function todoReducer(state = [], action) {
  if (action.type = 'add') {
    return [...state, action.payload];
  }
  return state;
}
medium
A. State should be an object, not an array
B. Missing default case in the reducer
C. Using assignment (=) instead of comparison (===) in the if condition
D. Reducer should not return a new array

Solution

  1. Step 1: Check the if condition syntax

    The condition uses single equals (=) which assigns instead of compares. This causes a bug.
  2. Step 2: Verify other parts

    Default case is handled by returning state. State as array is valid for todo list. Returning new array is correct for immutability.
  3. Final Answer:

    Using assignment (=) instead of comparison (===) in the if condition -> Option C
  4. Quick Check:

    Use '===' for comparison in conditions [OK]
Hint: Use '===' for comparisons, not '=' [OK]
Common Mistakes:
  • Confusing '=' with '===' in conditions
  • Thinking default case is missing
  • Believing state must be an object
5. You want to add a new feature to reset the counter state to zero using actions and reducers. Which of these is the best way to implement the reset action and update the reducer accordingly?
hard
A. Add case 'reset': state.count = 0; return state; directly in reducer without action
B. Define const reset = createAction('reset'); and add case 'reset': return { count: 0 }; in reducer
C. Define const reset = createAction('reset', () => 0); and return 0 in reducer
D. Use dispatch({ type: 'reset', count: 0 }) and ignore reducer changes

Solution

  1. Step 1: Define the reset action properly

    Use createAction with a string type 'reset' to define the action.
  2. Step 2: Update reducer to handle reset

    Add a case for 'reset' that returns a new state object with count set to 0, ensuring immutability.
  3. Final Answer:

    Define const reset = createAction('reset'); and add case 'reset': return { count: 0 }; in reducer -> Option B
  4. Quick Check:

    Action + reducer case resets state immutably [OK]
Hint: Create action and return new state in reducer [OK]
Common Mistakes:
  • Mutating state directly in reducer
  • Ignoring reducer update for new action
  • Misusing createAction with payload function