Hone logo
Hone
Problems

Implementing Optimistic Updates in an Angular Component

Optimistic updates enhance user experience by immediately reflecting changes on the UI before the server confirms the update. This challenge focuses on implementing optimistic updates in an Angular component that manages a list of items, providing a smoother and more responsive feel for the user. You'll be updating the UI immediately upon a button click, and then handling potential server errors gracefully.

Problem Description

You are tasked with creating an Angular component that displays a list of items and allows users to increment the count of each item. The component should implement optimistic updates: when a user clicks the "Increment" button for an item, the UI should immediately update the item's count before the server-side update is confirmed. If the server-side update fails, the UI should revert to the previous state.

Key Requirements:

  • Data Source: The component should fetch an initial list of items from a mock service (provided). Each item has an id (number) and a count (number).
  • UI Display: Display the list of items with their current counts.
  • Increment Button: Each item should have an "Increment" button.
  • Optimistic Update: Upon clicking "Increment," immediately update the item's count in the UI.
  • Server Simulation: Simulate a server update using a simulateUpdate function (provided). This function has a 50% chance of failing.
  • Error Handling: If the simulateUpdate function fails, revert the UI to the state before the optimistic update.
  • Loading State: While the server update is in progress, display a loading indicator (e.g., a spinner) next to the item being updated.

Expected Behavior:

  1. The component loads initially with data from the mock service.
  2. Clicking "Increment" immediately updates the count in the UI and displays a loading indicator.
  3. If the server update succeeds, the loading indicator disappears.
  4. If the server update fails, the count reverts to its previous value, and an error message (displayed in the console) indicates the failure. The loading indicator should also disappear.

Edge Cases to Consider:

  • What happens if the initial data load fails? (For simplicity, assume the mock service always returns data for this challenge).
  • How to handle multiple concurrent increment clicks on the same item? (For simplicity, assume clicks are serialized).
  • How to efficiently revert the UI to the previous state in case of an error?

Examples

Example 1:

Input: Initial data: [{id: 1, count: 5}, {id: 2, count: 10}]
User clicks "Increment" on item with id 1.
simulateUpdate returns success.
Output: [{id: 1, count: 6}, {id: 2, count: 10}]
Explanation: The count of item 1 is incremented to 6.

Example 2:

Input: Initial data: [{id: 1, count: 5}, {id: 2, count: 10}]
User clicks "Increment" on item with id 2.
simulateUpdate returns failure.
Output: [{id: 1, count: 5}, {id: 2, count: 10}]
Explanation: The count of item 2 reverts to 10, and an error is logged.

Example 3: (Edge Case - Error Handling)

Input: Initial data: [{id: 1, count: 5}]
User clicks "Increment" on item with id 1.
simulateUpdate returns failure.
Output: [{id: 1, count: 5}]
Explanation: The count reverts to 5, and an error is logged.

Constraints

  • Angular Version: Angular 14 or higher.
  • TypeScript: Use TypeScript.
  • Mock Service: You will be provided with a mock service that returns an array of items and a simulateUpdate function.
  • Performance: The UI should remain responsive even with multiple updates. Avoid unnecessary re-renders.
  • Error Handling: Errors should be logged to the console, but the application should not crash.

Notes

  • Consider using RxJS Observables to manage the asynchronous nature of the server updates.
  • Think about how to store the previous state of an item before the optimistic update so you can revert it in case of an error.
  • The loading indicator can be a simple CSS class that shows/hides a spinner.
  • Focus on the core logic of optimistic updates and error handling. Styling is not required.
  • The provided mock service will have a getItems() method that returns the initial data and a simulateUpdate(itemId: number, newCount: number) method that simulates the server update. The simulateUpdate method will return a Promise that resolves if the update is successful and rejects if it fails.
Loading editor...
typescript