typescript 类型“{}”上不存在属性“

2mbi3lxu  于 2023-04-22  发布在  TypeScript
关注(0)|答案(1)|浏览(630)

我正在尝试为我的登录页面设置一个上下文挂钩。我正在使用Typescript。我启动了上下文挂钩,但在声明类型时遇到了问题。当我尝试使用setUser时,这是弹出的错误:类型“{}”上不存在属性“setUser”。
这是我到目前为止的上下文挂钩。

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

这是我的登录码。

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
jv4diomz

jv4diomz1#

您需要为UserContext变量指定一个类型。因为您在createContext中给它一个参数{},typescript假设上下文的类型为React.Context<{}>。因此,当您尝试使用上下文对象时,您会得到一个{},一个空对象,它没有用户定义的属性。
首先,我将定义一个新接口,但您可以按自己的意愿键入它。

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

要声明UserContext的类型,您可以:
1.提供与类型匹配的默认值

export const UserContext = createContext<IUserContext>("<defaultValueHere>");

1.将默认上下文值设置为空对象/null

export const UserContext = createContext<IUserContext|{}>({});
export const UserContext = createContext<IUserContext|null>(null);

1.对空对象进行类型转换(不太类型安全)

export const UserContext = createContext<IUserContext>({} as IUserContext);

1.非空Assert(不太类型安全)

export const UserContext = createContext<IUserContext>(null!);

请注意,对于其中的一些,您需要稍后编写null检查。有关详细信息,请参阅here

相关问题