Hone logo
Hone
Problems

Implementing a useOptimistic Hook in React with TypeScript

Optimistic updates in React are a powerful technique for improving perceived performance and user experience. This challenge asks you to create a custom hook, useOptimistic, that allows you to update the state optimistically before the actual asynchronous operation (like a network request) completes. This provides immediate visual feedback to the user, making the application feel more responsive.

Problem Description

You need to implement a useOptimistic hook in React using TypeScript. This hook should take an initial state value and an update function as arguments. The update function will be called to generate a new optimistic state. The hook should then update the state optimistically, displaying the new state immediately. A rollback function will be provided to revert to the previous state if the asynchronous operation fails. The hook should manage the previous state and provide a mechanism to revert to it.

Key Requirements:

  • Optimistic Update: The hook should immediately update the state with the value returned by the update function.
  • Rollback Function: The hook should provide a rollback function that reverts the state to its previous value.
  • State Management: The hook should internally manage the previous state.
  • TypeScript: The hook must be written in TypeScript with appropriate type definitions.
  • Error Handling: The hook should not throw errors; the rollback function is the responsibility of the component using the hook.

Expected Behavior:

  1. When the component using the hook calls the update function, the state should be updated optimistically.
  2. The component should be able to call the rollback function to revert to the previous state.
  3. The hook should return the current state and the rollback function.

Edge Cases to Consider:

  • Initial state is null or undefined.
  • Update function returns null or undefined.
  • Multiple optimistic updates in quick succession.

Examples

Example 1:

Input:
initialState: 0
updateFn: (current) => current + 1
Output:
{
  state: 1,
  rollback: () => 0
}
Explanation: The state is updated optimistically from 0 to 1. The rollback function returns the original state, 0.

Example 2:

Input:
initialState: "Hello"
updateFn: (current) => current + " World"
Output:
{
  state: "Hello World",
  rollback: () => "Hello"
}
Explanation: The state is updated optimistically from "Hello" to "Hello World". The rollback function returns the original state, "Hello".

Example 3: (Edge Case)

Input:
initialState: null
updateFn: (current) => "New Value"
Output:
{
  state: "New Value",
  rollback: () => null
}
Explanation: The state is updated optimistically from null to "New Value". The rollback function returns the original state, null.

Constraints

  • The hook should be reusable across different components and state types.
  • The update function should accept the current state as an argument.
  • The rollback function should not take any arguments.
  • The hook should not introduce any unnecessary dependencies.
  • The hook should be performant and avoid unnecessary re-renders.

Notes

Consider using the useState hook internally to manage the state. The update function should be designed to be flexible enough to handle various state types. Think about how to handle the initial state gracefully, especially if it's null or undefined. The rollback function is crucial for error recovery; ensure it correctly reverts the state to its previous value. The hook should be designed to be as simple and efficient as possible.

Loading editor...
typescript