Home > OS >  How to use "useContext" in typescript?
How to use "useContext" in typescript?

Time:07-26

I am trying to make a dark/light theme system in my project, but I am having some problems with the code.

This line of code works fine in javascript:

const [darktheme, setDarkTheme] = useContext(ThemeContext);

But when I write it into typescript, I get 6 errors.

I know that some of these variables need to have their type declared, but I only know the type of the darkTheme variable, which is a boolean.

After I declare the types, 2 errors go away, but there is still 4 errors!

const [darktheme: boolean, setDarkTheme: any] = useContext(ThemeContext);

I used any after dark theme, which is not good practice but I didn't know the type

Now I just get these errors: enter image description here

enter image description here

I think that the main problem with my project is that I am trying to integrate javascript with typescript. I don't know if that is normal or not, but I am doing it because some components are much easier to write with typescript, and some more basic components are better written in javascript.

Here is part of my app.js:

// Context

export const ThemeContext = React.createContext();

function App() {
  const [darkTheme, setDarkTheme] = useState(false);

  return (
    <ThemeContext.Provider value={[darkTheme, setDarkTheme]}>

,and when I use the function in this component, it works just fine:

import React, { useContext } from 'react';
import { ThemeContext } from '../App';

import Button from 'react-bootstrap/Button';

export default function DarkThemeTest() {
    const [darktheme, setDarkTheme] = useContext(ThemeContext);

    return (
        <Button onClick={() => {
            setDarkTheme(!darktheme);
        }}>
            Theme: {darktheme && "Dark" || "Light"}
        </Button>
    )
}

CodePudding user response:

First, define a type for your context value

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

interface ThemeContextType {
  darkTheme: boolean;

  // this is the type for state setters
  setDarkTheme: Dispatch<SetStateAction<boolean>>; 
}

Then, create your context with this type and initialise it with a default value. This might seem unnecessary but it will avoid checking for null or undefined context later on

export const ThemeContext = createContext<ThemeContextType>({
  darkTheme: false,
  setDarkTheme: () => {}, // no-op default setter
});

Once you have created your state value and setter, set them into the context provider value

<ThemeContext.Provider value={{ darkTheme, setDarkTheme }}>

Now you can destructure the context value easily via useContext with full type support

const { darkTheme, setDarkTheme } = useContext(ThemeContext);

You could continue to use your array format though I wouldn't recommend it.

type ThemeContextType = [boolean, Dispatch<SetStateAction<boolean>>];

export const ThemeContext = createContext<ThemeContextType>([false, () => {}]);

and

<ThemeContext.Provider value={[darkTheme, setDarkTheme]}>
  • Related