Home > front end >  Passing setState function in createContext using Typescript
Passing setState function in createContext using Typescript

Time:10-17

I am trying to pass setState using create context but I have problem with declaring its default value. How I can do it so TS will not give me an error that types of properties are incompatible? How can declare its default value that it will actually fit type Dispatch<SetStateAction<string>>?

import { createContext, useState, useEffect } from "react";
import useLocalStorage from "../../hooks/useLocalStorage/";

interface DarkModeContextProviderProps {
  children?: React.ReactNode;
}

export const DarkModeContext = createContext({
  isDarkMode: false,
  darkModeState: "off",
  toggleIsDarkMode: () => {},
  setDarkModeState: () => {}, // ????
});

export const DarkModeContextProvider = ({
  children,
}: DarkModeContextProviderProps) => {
  const [isDarkMode, setIsDarkMode] = useState(false);
  const [darkModeState, setDarkModeState] = useState("");
  const [localStorageDarkMode, setLocalStorageDarkMode] = useLocalStorage(
    "darkModeState",
    darkModeState
  );

  const toggleIsDarkMode = () => {
    setIsDarkMode((prev) => !prev);
  };

  const value = {
    isDarkMode,
    toggleIsDarkMode,
    darkModeState,
    setDarkModeState,
  };
  useEffect(() => {
    setDarkModeState(localStorageDarkMode);
  }, []);
  useEffect(() => {
    setLocalStorageDarkMode(darkModeState);
  }, [darkModeState]);

  return (
    <DarkModeContext.Provider value={value}>
      {children}
    </DarkModeContext.Provider>
  );
};

CodePudding user response:

You can do this creating a type/interface for the context

import type { Dispatch, SetStateAction } from "react";

interface IDarkModeContext {
  isDarkMode: boolean;
  darkModeState: string;
  toggleIsDarkMode: Dispatch<SetStateAction<string>>;
  setDarkModeState: Dispatch<SetStateAction<string>>;
}

export const DarkModeContext = createContext<IDarkModeContext>({
  isDarkMode: false,
  darkModeState: "off",
  toggleIsDarkMode: () => {},
  setDarkModeState: () => {},
});

CodePudding user response:

You cannot have a default state setter since you have to create your context outside and state setters only live inside a component. What you can do and that's common is to define a DarkModeContextInterface and use it like so:

interface DarkModeContextInterface {
  isDarkMode: boolean;
  darkModeState: string;
  toggleIsDarkMode: Dispatch<SetStateAction<string>>;
  setDarkModeState: Dispatch<SetStateAction<string>>;
}
export const DarkModeContext = createContext<DarkModeContextInterface | null>(null)

Here is how you would use it:

// the "!" is to tell Typescript that it won't be null, the default value
cont {isDarkMode} = useContext(DarkModeContext)!; 
  • Related