Hone logo
Hone
Problems

Angular Component Store Implementation

This challenge asks you to implement a simple component store in Angular using TypeScript. A component store is a pattern that allows you to manage and share state related to a specific component across its instances and potentially other components, promoting reusability and simplifying state management. This is particularly useful for components that require complex data handling or interactions.

Problem Description

You need to create a generic ComponentStore class in Angular that can be used to manage the state of a component. The store should provide methods for:

  1. Initializing the state: The store should accept an initial state object during its construction.
  2. Getting the current state: A method to retrieve the current state.
  3. Updating the state: A method to update the state. This method should accept a function that takes the current state as input and returns the new state. This allows for immutable state updates.
  4. Subscribing to state changes: A method that allows subscribers to receive notifications whenever the state changes. This should return an Unsubscribe function to stop listening.

The ComponentStore should be designed to be reusable across different components and state types.

Key Requirements:

  • The store must be generic, accepting a type parameter for the state.
  • State updates must be immutable (i.e., create a new state object instead of modifying the existing one).
  • The subscription mechanism should use RxJS Subject to handle asynchronous state changes.
  • The store should be testable.

Expected Behavior:

  • The store should initialize with the provided initial state.
  • getState() should return the current state.
  • updateState(stateUpdateFn) should update the state using the provided function and emit a new state value.
  • subscribe(next) should return an unsubscribe function. Calling unsubscribe() should stop receiving state updates.

Edge Cases to Consider:

  • What happens if updateState is called with a function that doesn't return a new state? (Consider throwing an error or returning the original state).
  • How should the store handle multiple subscribers?
  • How to ensure immutability of state?

Examples

Example 1:

Input:
Initial State: { count: 0 }
updateState(state => ({ ...state, count: state.count + 1 }))
subscribe(count => console.log(count))
Output:
Console Log: 1
Current State: { count: 1 }

Explanation: The state is initialized with count: 0. The updateState function increments the count by 1, resulting in a new state { count: 1 }. The subscriber receives the new state value.

Example 2:

Input:
Initial State: { name: "Guest", isLoggedIn: false }
updateState(state => ({ ...state, isLoggedIn: true }))
subscribe(authState => console.log(authState.isLoggedIn))
unsubscribe()
updateState(state => ({ ...state, name: "John" }))
Output:
Console Log: true
(No further console logs)

Explanation: The state is initialized with name: "Guest" and isLoggedIn: false. The updateState function sets isLoggedIn to true. The subscriber receives true. The unsubscribe() function is called, preventing further state updates from being logged. A subsequent state update is ignored by the unsubscribed subscriber.

Example 3: (Edge Case)

Input:
Initial State: { data: [] }
updateState(state => state) // Function returns the same object
Output:
No state change.  Error thrown (or original state returned, depending on implementation).

Explanation: The updateState function is called with a function that returns the original state object. The store should either throw an error indicating an invalid state update or return the original state without emitting a new value.

Constraints

  • The ComponentStore class must be written in TypeScript.
  • The store must use RxJS Subject for state change notifications.
  • State updates must be immutable.
  • The store should be generic.
  • The updateState function must accept a function that takes the current state and returns the new state.
  • The subscribe method must return an Unsubscribe function.
  • The solution should be well-structured and easy to understand.

Notes

  • Consider using the spread operator (...) to create new state objects for immutable updates.
  • Think about how to handle errors gracefully, especially when the updateState function is invalid.
  • Focus on creating a reusable and testable ComponentStore class.
  • You don't need to implement a full-fledged state management library; the goal is to demonstrate the core concepts of a component store.
  • Testability is key. Consider how you would test the different methods of the store.
Loading editor...
typescript