Always Use a Custom Hook for Context API, Not useContext (React Context API, TypeScript)
Step 1: Create the Theme Context
First, we need to create the context for our theme.
import React, { createContext, useState } from 'react';
type Theme = 'dark' | 'light';
type ThemeContextProps = {
theme: Theme;
setTheme: React.Dispatch<React.SetStateAction<Theme>>;
};
const ThemeContext = createContext<ThemeContextProps | null>(null);
Here, we're defining the types for our theme and setting the initial value as null.
Step 2: Implementing the Theme Context Provider
Now, we will implement the provider for the theme context.
type ThemeContextProviderProps = { children: React.ReactNode; };
function ThemeProvider(props: ThemeContextProviderProps) {
const [theme, setTheme] = useState<Theme>('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{props.children}
</ThemeContext.Provider>
);
};
The ThemeProvider wraps the root component of your application and passes down the theme and a function to set the theme.
Step 3: Creating a Custom Hook
Using useContext
directly can be cumbersome as you'll have to import the context and check for null every time. Instead, create a custom hook to handle this.
export const useThemeContext = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useThemeContext must be used within a ThemeContextProvider');
}
return context;
};
Now, whenever you want to access the theme or set it in any component, you can simply call this custom hook.
Step 4: Consuming the Context
Here's an example of how to use the custom hook within a component.
const Logo = () => {
const { theme } = useThemeContext();
return theme === 'dark' ? <DarkModeLogo /> : <LightModeLogo />;
};