'How to correctly use Context API and Provider
I'm implementing a dark mode, and I got stuck at this part of my project, where everything looks like working, but don't. There is no error, but my Context at App, don't re-render when I use the setTheme inside the Provider, how can I fix it ?
App.jsx
import { useContext } from "react"
import { ThemeLocalContext, ThemeLocalProvider } from "./context/ThemeContext"
import { ThemeProvider } from "styled-components"
import {Paths} from "./pages/Paths/"
import { GlobalStyle } from "./styles/GlobalStyle/GlobalStyle"
function App() {
const theme = useContext(ThemeLocalContext);
console.log(theme)
return (
<div>
<ThemeLocalProvider>
<>
<ThemeProvider theme={theme}>
<GlobalStyle/>
<Paths/>
</ThemeProvider>
</>
</ThemeLocalProvider>
</div>
)
}
export default App
ThemeContext.jsx
import React, { createContext, useState } from "react";
import { lightTheme } from "../styles/Theme/lightTheme";
import { darkTheme } from "../styles/Theme/darkTheme";
export const ThemeLocalContext = createContext(lightTheme);
export const ThemeLocalProvider = ({children}) => {
const [theme, setTheme] = useState(darkTheme);
const handleChange = () => {
setTheme(theme.title === 'light'? darkTheme : lightTheme)
}
return (
<ThemeLocalContext.Provider value={[theme, handleChange]}>
{children}
</ThemeLocalContext.Provider>
)
}
I don't think the error is here, but I'll also let my Header code here, this is where I run the setTheme function, who is named by handleChange, and I use it whit theme[1].
Header.jsx
import ReactSwitch from "react-switch";
import {useContext, useState} from 'react'
import { ThemeLocalContext } from "../../context/ThemeContext";
const Header = () => {
const theme = useContext(ThemeLocalContext)
return(
<div>
<h1>{theme[0].colors.primary}</h1>
<ReactSwitch
checked={theme[0].title === 'dark'}
onChange={theme[1]}
/>
</div>
)
}
export default Header;
Solution 1:[1]
The reason because this code was not working, is the placement of my context, calling it at my <App/>, I was calling it outside the <ThemeLocalProvider/>.
I put the <ThemeLocalProvider/> at main.jsx, and it worked.
Solution 2:[2]
You need to pass only theme object to ThemeProvider.
You need to get only theme object from your context.
Using const [theme] = useContext(ThemeLocalContext);
App.jsx
import { useContext } from "react"
import { ThemeLocalContext, ThemeLocalProvider } from "./context/ThemeContext"
import { ThemeProvider } from "styled-components"
import {Paths} from "./pages/Paths/"
import { GlobalStyle } from "./styles/GlobalStyle/GlobalStyle"
function App() {
const [theme] = useContext(ThemeLocalContext);
console.log(theme)
return (
<div>
<ThemeLocalProvider>
<>
<ThemeProvider theme={theme}>
<GlobalStyle/>
<Paths/>
</ThemeProvider>
</>
</ThemeLocalProvider>
</div>
)
}
export default App
For better code
Header.jsx
import ReactSwitch from "react-switch";
import {useContext, useState} from 'react'
import { ThemeLocalContext } from "../../context/ThemeContext";
const Header = () => {
const [theme, toggleTheme] = useContext(ThemeLocalContext)
return(
<div>
<h1>{theme.colors.primary}</h1>
<ReactSwitch
checked={theme.title === 'dark'}
onChange={toggleTheme}
/>
</div>
)
}
export default Header;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Maiky |
| Solution 2 | Chirag Shah |
