Search code examples
reactjstypescripttypesreact-context

What is defaultValue type for createContext which value's type is React.ProviderProps<unknown>.value: unknown?


I'm implementing theme toggler to my website with createContext and I run into this error:

'Expected 1 arguments, but got 0.ts(2554) An argument for 'defaultValue' was not provided.'

I know that I need to pass default value to const ThemeUpdateContext = React.createContext(), but I'm using this createContext for a function, that doesn't return anything. What is the best way to define defaultValue here?

Here is my code:

import React, { useState, useContext, ReactNode } from 'react'

const ThemeContext = React.createContext(true)
const ThemeUpdateContext = React.createContext()

export const useTheme = () => {
  const context = useContext(ThemeContext)
  if (context === undefined) {
    throw Error('ThemeContext must be within ThemeProvider')
  }
  return context
}

export const useUpdateTheme = () => {
  const context = useContext(ThemeUpdateContext)
  if (context === undefined) {
    throw Error('ThemeUpdateContext must be within ThemeProvider')
  }
  return context
}

const ThemeProvider = ({ children }: { children: ReactNode }) => {
  const [darkTheme, setDarkTheme] = useState(true)

  const toggleTheme = () => {
    setDarkTheme((prev) => !prev)
  }

  return (
    <ThemeContext.Provider value={darkTheme}>
      <ThemeUpdateContext.Provider value={toggleTheme}>
        {children}
      </ThemeUpdateContext.Provider>
    </ThemeContext.Provider>
  )
}

Solution

  • In your code, you are not passing defaultValue as function in ThemeUpdateContext.

    To fix this error, you can try this:

    const ThemeUpdateContext = React.createContext(() => {});
    

    Alternatively, you can use only one Context.

    For example:

    import React, { useState, useContext, ReactNode } from "react";
    
    type ThemeContextType = {
      theme: boolean;
      toggleTheme: () => void;
    };
    
    const ThemeContext = React.createContext<ThemeContextType>({
      theme: true,
      toggleTheme: () => {},
    });
    
    export const useTheme = () => {
      const { theme } = useContext(ThemeContext);
      return theme;
    };
    
    export const useUpdateTheme = () => {
      const { toggleTheme } = useContext(ThemeContext);
      return toggleTheme;
    };
    
    export const ThemeProvider = ({ children }: { children: ReactNode }) => {
      const [darkTheme, setDarkTheme] = useState(true);
    
      const toggleTheme = () => {
        setDarkTheme((prev) => !prev);
      };
    
      return (
        <ThemeContext.Provider value={{ theme: darkTheme, toggleTheme }}>
          {children}
        </ThemeContext.Provider>
      );
    };