Home > OS >  How to correctly use Context API and Provider
How to correctly use Context API and Provider

Time:04-15

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;

CodePudding user response:

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;

CodePudding user response:

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.

  • Related