Hone logo
Hone
Problems

Implementing a useContrastMode Hook for Dynamic Theme Switching in React

This challenge focuses on creating a reusable React hook, useContrastMode, that manages and provides a state variable for toggling between a light and dark contrast mode. This hook will be useful for building applications with user-configurable themes, enhancing accessibility and user experience. The hook should persist the user's preference across re-renders and potentially across page refreshes (though persistence is not a core requirement for this challenge).

Problem Description

You are tasked with implementing the useContrastMode hook in TypeScript. This hook should:

  1. Initialize State: Start with a default contrast mode (either 'light' or 'dark' - you can choose the default).
  2. Toggle Mode: Provide a function to toggle between 'light' and 'dark' contrast modes.
  3. Return Values: Return an array containing:
    • The current contrast mode string ('light' or 'dark').
    • A function to toggle the contrast mode.
  4. Persistence (Optional): Ideally, the hook should attempt to persist the contrast mode preference using localStorage. If localStorage is unavailable (e.g., in a server-side rendering environment), it should gracefully fall back to only managing the state in memory.
  5. Update on Change: When the contrast mode is toggled, the hook should update localStorage (if available) to persist the new preference.

Expected Behavior:

  • On initial mount, the hook should check localStorage for a saved contrast mode. If found, it should initialize the state with that value. Otherwise, it should use the default.
  • Toggling the mode should update the state and, if available, localStorage.
  • Subsequent mounts should retrieve the saved contrast mode from localStorage (if present) and initialize the state accordingly.

Examples

Example 1:

Input: Initial state is 'light', localStorage is empty.
Output: ['light', toggleContrastMode]
Explanation: The hook initializes with 'light' because it's the default and localStorage is empty.  `toggleContrastMode` is a function that, when called, will change the state to 'dark' and update localStorage.

Example 2:

Input: Initial state is 'light', localStorage contains 'dark'.
Output: ['dark', toggleContrastMode]
Explanation: The hook initializes with 'dark' because it finds 'dark' in localStorage. `toggleContrastMode` is a function that, when called, will change the state to 'light' and update localStorage.

Example 3: (Edge Case - localStorage unavailable)

Input: Initial state is 'light', localStorage is unavailable (e.g., server-side rendering).
Output: ['light', toggleContrastMode]
Explanation: The hook initializes with 'light' as the default.  `toggleContrastMode` will update the state in memory, but will *not* attempt to update localStorage.

Constraints

  • The hook must be written in TypeScript.
  • The contrast mode state must be strictly either 'light' or 'dark'.
  • The hook should handle the case where localStorage is not available gracefully (without throwing errors).
  • The hook should be reusable in any React component.
  • The toggleContrastMode function should be a stable function reference (i.e., it shouldn't change on every render).

Notes

  • Consider using useState to manage the contrast mode state.
  • Use localStorage.getItem and localStorage.setItem to interact with localStorage.
  • You can use a try-catch block to handle potential errors when accessing localStorage.
  • Think about how to handle the initial state when localStorage is unavailable.
  • Focus on creating a clean, well-documented, and reusable hook. Error handling for localStorage is important, but the core functionality is the state management and toggling.
Loading editor...
typescript