I'm trying to set up a context hook for my login page. I'm using typescript. I started the context hook but I'm having trouble with type declarations. When I try to use setUser, the following error pops up: Property 'setUser' does not exist on type '{}'.
This is my context hook so far.
import { createContext, ReactNode, useEffect, useState } from "react" interface Props { children?: ReactNode } export const UserContext = createContext({}) export function UserContextProvider({children}: Props) { const [user, setUser] = useState(null) return ( <UserContext.Provider value={{user, setUser}}> {children} </UserContext.Provider> ) }
This is my login code.
import { Link, Navigate } from "react-router-dom" import axios from 'axios' import { UserContext } from "../UserContext" const Login = () => { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [redirect, setRedirect] = useState(false) **const {setUser} = useContext(UserContext)** async function handleLogin(e: any) { e.preventDefault() try { const userInfo = await axios.post('/auth/login', {email, password}) setUser(userInfo) alert('Login') setRedirect(true) } catch (e) { alert('Login failed') } } if(redirect){ return <Navigate to={'/'} /> } return ( <div> <div> <h1>Login</h1> <form onSubmit={handleLogin}> <input type="email" placeholder="your@email.com" value={email} onChange={e => setEmail(e.target.value)}/> <input type="password" placeholder="password" value={password} onChange={e => setPassword(e.target.value)}/> <button>Login</button> <div> Don't have an account? <Link to={"/auth/register"}> Sign Up</Link> </div> </form> </div> </div> ) } export default Login
You need to specify the type for the
UserContext
variable. Because you gave it a{}
parameter increateContext
, Typescript assumes that the context is of typeReact.Context<{}>
. So when you try to use the context object, you get a{}
, an empty object, which has no user-defined properties.First I will define a new interface, but you can type it if you want.
To declare the type of
UserContext
, you can:Provide a default value that matches the type
Set the default context value to the empty object/null
Type conversion of empty objects (poor type safety)
Non-null assertion (poor type safety)
Note that for some of these you will need to write a null check later. See here for more information.