React useContext传递useState属性时触发TypeScript类型错误
解决React Context结合TypeScript时的属性不存在错误
你遇到的错误核心是Context的类型定义过于宽泛:使用<Object>作为createContext的泛型参数后,TypeScript无法识别currentUser和setCurrentUser这两个自定义属性,因此解构时会提示属性不存在。
以下是具体修复步骤:
步骤1:定义Context的具体类型接口
先明确描述Context的结构,同时定义用户数据的类型:
// 定义用户数据的类型 interface User { name: string; } // 定义Context的完整类型 interface CurrentUserContextType { currentUser: User | null; setCurrentUser: React.Dispatch<React.SetStateAction<User | null>>; }
步骤2:用正确类型创建Context
替换原来的createContext<Object>({}),使用上面定义的接口,并提供符合类型的默认值(避免组件在Provider外部使用时报错):
const CurrentUserContext = createContext<CurrentUserContextType>({ currentUser: null, setCurrentUser: () => {}, // 空函数作为默认的setter });
步骤3:修正useState的类型
原来的useState(null)会被TypeScript推断为null类型,需要明确指定为User | null:
const [currentUser, setCurrentUser] = useState<User | null>(null);
完整修复后的代码
import { createContext, useContext, useState, ReactNode, DetailedHTMLProps, ButtonHTMLAttributes, MouseEventHandler } from 'react'; // 新增用户类型定义 interface User { name: string; } // 新增Context类型定义 interface CurrentUserContextType { currentUser: User | null; setCurrentUser: React.Dispatch<React.SetStateAction<User | null>>; } // 用正确的类型创建Context并设置符合类型的默认值 const CurrentUserContext = createContext<CurrentUserContextType>({ currentUser: null, setCurrentUser: () => {}, }); export default function MyApp() { // 明确useState的类型 const [currentUser, setCurrentUser] = useState<User | null>(null); return ( <CurrentUserContext.Provider value={{ currentUser, setCurrentUser }} > <Form /> </CurrentUserContext.Provider> ); } function Form(): JSX.Element { return ( <Panel title="Welcome"> <LoginButton /> </Panel> ); } function LoginButton(): JSX.Element { const { currentUser, setCurrentUser } = useContext(CurrentUserContext); if (currentUser !== null) { return <p>You logged in as {currentUser.name}.</p>; } return ( <Button onClick={() => { setCurrentUser({ name: 'Advika' }) }}>Log in as Advika</Button> ); } interface PanelProps { title: string children: ReactNode } function Panel({ title, children }: PanelProps): JSX.Element { return ( <section className="panel"> <h1>{title}</h1> {children} </section> ) } interface ButtonProps extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> { children: ReactNode onClick?: MouseEventHandler<HTMLButtonElement> } function Button({ children, onClick }: ButtonProps): JSX.Element { return ( <button className="button" onClick={onClick}> {children} </button> ); }
内容的提问来源于stack exchange,提问作者Lvasche
相关产品推荐
相关产品推荐

