Hone logo
Hone
Problems

Implementing a useLocalStorage Hook in React with TypeScript

This challenge asks you to create a custom React hook, useLocalStorage, that allows components to read and write data to the browser's local storage. This is a common pattern for persisting component state across page reloads or browser sessions, providing a simple alternative to more complex state management solutions for specific use cases. Successfully implementing this hook will enable you to easily manage persistent data within your React components.

Problem Description

You need to implement a useLocalStorage hook in TypeScript. This hook should accept a key (string) as an argument and return a tuple containing:

  1. The current value stored in local storage for the given key. If the key doesn't exist in local storage, the initial value should be used (see below).
  2. A function to update the value stored in local storage for the given key.

The hook should handle the following:

  • Initialization: When the component using the hook first mounts, it should attempt to read the value associated with the provided key from local storage. If the key doesn't exist, it should use the provided initial value.
  • Type Safety: The hook should be type-safe, ensuring that the value read from local storage and the value passed to the update function are of the correct type.
  • Persistence: Updates to the value should be immediately persisted to local storage.
  • Error Handling: The hook should gracefully handle potential errors during local storage access (though errors are rare, it's good practice).
  • Initial Value: The hook should accept an initial value as a second argument. This value will be used if the key is not found in local storage. The initial value can be of any type.

Expected Behavior:

  • The hook should return a tuple: [value: T, setLocalStorage: (newValue: T) => void] where T is the type of the initial value.
  • Reading from local storage should parse the stored value as JSON.
  • Writing to local storage should stringify the new value as JSON.
  • The setLocalStorage function should update both the local storage and the component's state.

Examples

Example 1:

Input: useLocalStorage("myCounter", 0)
Output: [0, (newValue: number) => void]
Explanation:  Initially, local storage doesn't have "myCounter". The hook reads the initial value (0) and returns it along with a setter function.  Calling the setter with `useLocalStorage("myCounter", 0)[1](1)` will store 1 in local storage and update the component's state.

Example 2:

Input: useLocalStorage("name", "Guest")
Output: ["Guest", (newValue: string) => void]
Explanation:  Local storage has "name" set to "OldName". The hook reads "OldName" from local storage. Calling the setter with `useLocalStorage("name", "Guest")[1]("John")` will store "John" in local storage and update the component's state.

Example 3:

Input: useLocalStorage("darkMode", false)
Output: [false, (newValue: boolean) => void]
Explanation: Local storage doesn't have "darkMode". The hook reads the initial value (false) and returns it along with a setter function.

Constraints

  • The hook must be written in TypeScript.
  • The hook must use the useState and useEffect hooks from React.
  • The hook must correctly handle JSON serialization and deserialization.
  • The hook must not cause unnecessary re-renders.
  • The key must be a string.
  • The initial value can be of any type.

Notes

  • Consider using localStorage.getItem() and localStorage.setItem() for interacting with local storage.
  • Think about how to handle the initial value when the key doesn't exist in local storage.
  • Pay attention to type safety when reading and writing values to local storage. Remember that local storage only stores strings.
  • Use useEffect to synchronize the component's state with local storage.
  • Consider using JSON.parse() and JSON.stringify() to convert between JavaScript objects and strings for local storage.
  • Error handling is not strictly required, but demonstrating awareness of potential errors is a plus.
Loading editor...
typescript