Implementing a Custom Context Hook for Theme Management in React
Context provides a way to pass data through the component tree without having to pass props down manually at every level. This challenge asks you to build a custom context hook, useTheme, to manage a theme (light or dark) within a React application. This is a common pattern for managing global application state like themes, user preferences, or authentication status.
Problem Description
You need to create a custom React context and a corresponding hook, useTheme, that allows components to access and update the current theme (either "light" or "dark"). The context should provide a theme value (string: "light" or "dark") and a setTheme function to update the theme. The useTheme hook should return an array containing the theme value and the setTheme function.
Key Requirements:
- Context Creation: Create a React Context specifically for theme management.
- Provider Component: Implement a
ThemeProvidercomponent that accepts achildrenprop and provides the theme value and update function to its descendants. - Custom Hook (
useTheme): Create a custom hook nameduseThemethat utilizes the context to return the current theme and thesetThemefunction. - Theme Updates: The
setThemefunction should update the theme value and trigger a re-render in components consuming the context. - Initial Theme: The context provider should initialize the theme to "light".
Expected Behavior:
- Components using the
useThemehook should receive the current theme value. - Calling the
setThemefunction returned by the hook should update the theme value and cause all components consuming the context to re-render with the new theme. - The
ThemeProvidershould correctly provide the theme and update function to its children.
Edge Cases to Consider:
- Ensure the
setThemefunction correctly updates the context value. - Consider how the context will behave when a component is unmounted. (No specific handling is required, but be mindful of potential memory leaks if you were to add complex cleanup logic).
- The theme value should always be either "light" or "dark". While validation isn't strictly required, consider how you might handle invalid theme values in a production environment.
Examples
Example 1:
Input: A React application with a ThemeProvider wrapping a component using useTheme. Initial theme is "light". The useTheme hook is called and setTheme("dark") is invoked.
Output: The theme value changes to "dark". All components consuming the context re-render with the "dark" theme.
Explanation: The setTheme function updates the context value, triggering a re-render of all components subscribed to the context.
Example 2:
Input: A React application with a ThemeProvider and multiple components using useTheme.
Output: All components using useTheme have access to the current theme value and the setTheme function.
Explanation: The ThemeProvider makes the theme context available to all its children.
Example 3: (Edge Case - Nested Providers)
Input: A React application with nested ThemeProviders.
Output: The innermost ThemeProvider's value takes precedence.
Explanation: React Context values are resolved from the nearest provider in the component tree.
Constraints
- The solution must be written in TypeScript.
- The
themevalue must be a string, either "light" or "dark". - The
setThemefunction must accept a string ("light" or "dark") as an argument. - The solution should be reasonably performant; avoid unnecessary re-renders.
- The code should be well-structured and easy to understand.
Notes
- Think about how to create the context and provider components.
- Consider how to use the
useContexthook within your custom hook. - Focus on creating a reusable and maintainable solution.
- You don't need to create a full UI with styling; the focus is on the context and hook implementation. You can use simple console logs to verify the theme changes.