Using context in your react app is really useful, when you are passing some prop to multiple nested elements for example Theme
How to use it?
In this example we will make Theme provider.
Create ThemeProvider.tsx
It will hold our wrapper that implements the theme for all child components.
- We make enum for Theme Options
- Make ThemeContext with createContext<type of the context>( initial state)….(we need to supply the initial state so it is the right type of prop)
- export the ThemeProvider where we provide children as prop so that we can pass all children
- define state that we would be saving throughout the whole app
- add ThemeContext.Provider value={{state: themeState,switchTheme: themeStateDispatch}}
- pass children
TSX
import { Dispatch, SetStateAction, createContext, useState } from 'react';
import React from 'react'
export enum ThemeOptions {
light = "light",
dark = "dark"
}
export const ThemeContext = createContext<{
state: ThemeOptions;
switchTheme: Dispatch<SetStateAction<ThemeOptions>>;
}>(
{
state: ThemeOptions.light,
switchTheme: () => { }
});
export const initialThemeState = ThemeOptions.light
// write a reducer for theme
export default function ThemeProvider({ children }: { children: React.ReactNode }) {
const [themeState, themeStateDispatch] = useState(initialThemeState);
return (
<div>ThemeProvider
<ThemeContext.Provider value={{state: themeState,switchTheme: themeStateDispatch}}>
{children}
</ThemeContext.Provider>
</div>
)
}
Then make Class or functional component that implements this context
Functional example:
TSX
import React, { useContext } from 'react'
import { ThemeContext } from '../context/ThemeProvider'
export default function FunctionalComponent() {
const value = useContext(ThemeContext)
return <div>{value.state}</div>
}
Class example:
TSX
import React, { Component } from 'react';
import { ThemeContext } from '../context/ThemeProvider';
class ClassComponent extends Component {
render() {
return (
<ThemeContext.Consumer>
{value => <div>{value.state}</div>}
</ThemeContext.Consumer>
);
}
}
export default ClassComponent;
Wrap all the components that read or change context in the app.tsx:
TSX
// App.tsx
import React, { useContext } from 'react';
import './App.css';
import { ThemeContext, ThemeOptions, } from './context/ThemeProvider';
import ClassComponent from './components/classComponent';
import FunctionalComponent from './components/functionalComponent';
import ThemeProvider from './context/ThemeProvider';
function App() {
return (
<div className="App">
<ThemeProvider >
<ThemeSwitcherButton />
<ClassComponent />
<FunctionalComponent />
</ThemeProvider>
</div>
);
}
function ThemeSwitcherButton() {
const themeContextValue = useContext(ThemeContext)
return (
<button onClick={() => {
themeContextValue.switchTheme(themeContextValue.state === ThemeOptions.dark ? ThemeOptions.light : ThemeOptions.dark)
}}>
Change Theme
</button>
)
}
export default App;
And that’s it, we have just made theme with button to switch and components that read the value and that we can use in our app.
I hope this explained this well.
Happy coding
Leave a Reply