Skip to content

ThemeProvider: “theme” prop is required. → React.js

🐛 Issue

I created a Custom Hook to switch themes, but I’m facing this problem and I don’t exactly what could it be.

Basically, when I try to change the theme, it works perfectly. But, after refreshing the page, it doesn’t stay with the correct one and gives me this error.

⚙️ Reproduce the issue

You can reproduce this issue, cloning the Edite GitHub repository and follow the guide to set up the services.

💻 Code

Note: see that src is the root

hooks/useThemeSwitcher.js

import { useState, useEffect } from 'react';

function useThemeSwitcher(key, initialTheme) {
  const [theme, setTheme] = useState(
    () => {
      let storagedTheme = localStorage.getItem(key);
      storagedTheme = JSON.parse(storagedTheme) || initialTheme;
    }
  );

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(theme));
  }, [key, theme]);

  return [theme, setTheme];
}

export default useThemeSwitcher;

App.js

function App() {
  // Current theme state (light/dark);
  const [theme, setTheme] = useThemeSwitcher('theme', dark);

  const toggleTheme = () => {
    setTheme(theme.title === 'dark' ? light : dark)
  }

  return (
    <ThemeProvider theme={theme}>
      <Global />
      {/* ...components */}
      <ToolbarLeft toggleTheme={toggleTheme} />
    </ThemeProvider>
  );
}

components/Switch/index.js

// Components (styles)
import { CustomSwitch } from './switch.styles';

function Switch({ isToggled, onSwitch }) {
  return (
    <CustomSwitch>
      <input
        type="checkbox"
        checked={isToggled}
        onChange={onSwitch}
      />
      <span />
    </CustomSwitch>
  )
}

export default Switch;

components/Toolbar/Left/index.js

// Components (styles)
import { LeftContainer } from '../toolbar.styles';
// Components (children)
import ToolsList from './tools';

function ToolbarLeft({ toggleTheme }) {
  return (
    <LeftContainer>
      <ul>
        <ToolsList toggleTheme={toggleTheme} />
      </ul>
    </LeftContainer>
  )
}

export default ToolbarLeft;

components/Toolbar/Left/tools.js

function ToolsList({ toggleTheme }) {
  // Access and set the theme colors
  const { title } = useContext(ThemeContext);

  return (
    <>
      {/* ...components */}
      {/* Theme switcher */}
      <Switch
        isToggled={title === 'dark'}
        onSwitch={toggleTheme}
      </Switch>
    </>
  )
}

Answer

The problem is that you are not returning storagedTheme inside your useThemeSwitcher hook.


So you could change your useThemeSwitcher.js to something like this:

import { useState, useEffect } from "react";

function useThemeSwitcher(key, initialTheme) {
  const [theme, setTheme] = useState(() => {
    let storagedTheme = localStorage.getItem(key);
    return JSON.parse(storagedTheme) || initialTheme;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(theme));
  }, [key, theme]);

  return [theme, setTheme];
}

export default useThemeSwitcher;