search

Home  >  Q&A  >  body text

Type '{}' has no attribute ''

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

P粉615829742P粉615829742242 days ago361

reply all(1)I'll reply

  • P粉998100648

    P粉9981006482024-03-27 00:40:12

    You need to specify the type for the UserContext variable. Because you gave it a {} parameter in createContext, Typescript assumes that the context is of type React.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.

    interface IUserContext {
      user: any;
      setUser: any; //set your definitions here (please don't use `any`)
    }
    

    To declare the type of UserContext, you can:

    1. Provide a default value that matches the type

      export const UserContext = createContext("");
      
    2. Set the default context value to the empty object/null

      export const UserContext = createContext({});
      export const UserContext = createContext(null);
      
    3. Type conversion of empty objects (poor type safety)

      export const UserContext = createContext({} as IUserContext);
      
    4. Non-null assertion (poor type safety)

      export const UserContext = createContext(null!);
      

    Note that for some of these you will need to write a null check later. See here for more information.

    reply
    0
  • Cancelreply