Search code examples
reactjstypescriptreact-hooksreact-context

I'm having trouble implenting "useContext" with typeScript in my app


I had no problem using context in regular JS but typeScript is giving me a hard time. I've read over the docs and looked at some examples but I'm still missing something. Any help would be greatly appreciated, thanks!

Context Component

import { ReactNode, createContext, useState } from 'react'

const DialogContext = createContext<DialogContext | null>(null)

function DialogProvider({ children }: { children: ReactNode }) {
  const [player1ButtonText, setPlayer1ButtonText] = useState('SELECT PLAYER 1')
  const [player2ButtonText, setPlayer2ButtonText] = useState('SELECT PLAYER 2')
  const [open, setOpen] = useState(false)
  function handleOpen() {
    setOpen(true)
  }
  function handleClose() {
    setOpen(false)
  }

  return (
    <DialogContext.Provider
      value={{
        open,
        handleOpen,
        handleClose,
        player1ButtonText,
        setPlayer1ButtonText,
        player2ButtonText,
        setPlayer2ButtonText,
      }}
    >
      {children}
    </DialogContext.Provider>
  )
}

export { DialogProvider, DialogContext }

Component using context

export default function SelectPlayerBox() {
  const { handleOpen, player1ButtonText, player2ButtonText } =
    useContext(DialogContext)
  return (...

App component

...
<DialogProvider>
   <SelectPlayerBox />
</DialogProvider>
...

Solution

  • You need to define the type of your context value explicitly and pass it as a generic parameter to the createContext function. This way, TypeScript can infer the type of your context value and check if it matches the value you pass to the Provider component.

    For example:

    type DialogContextType = {
      player1ButtonText: string;
      setPlayer1ButtonText: (text: string) => void;
      player2ButtonText: string;
      setPlayer2ButtonText: (text: string) => void;
      open: boolean;
      handleOpen: () => void;
      handleClose: () => void;
    };
    
    const DialogContext = createContext<DialogContextType>({
      player1ButtonText: "SELECT PLAYER 1",
      setPlayer1ButtonText: () => {},
      player2ButtonText: "SELECT PLAYER 2",
      setPlayer2ButtonText: () => {},
      open: false,
      handleOpen: () => {},
      handleClose: () => {}
    });
    

    You can see the whole example here: codesandbox.io