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
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]}>