为何TypeScript无法识别Context包装器提供的值?
解决React Context的TypeScript解构错误
错误原因
你定义的NavContext类型是NavContextType | null,当使用useContext获取值时,TypeScript无法确定返回的是NavContextType还是null,直接解构null会触发属性不存在的错误。
解决方案
方案1:给Context提供符合类型的默认值
修改Context的创建代码,去掉null类型,直接提供一个符合NavContextType的默认值:
type NavContextType = { isDrawerOpen: boolean; setIsDrawerOpen: React.Dispatch<React.SetStateAction<boolean>>; }; // 提供默认值,类型不再包含null export const NavContext = createContext<NavContextType>({ isDrawerOpen: false, setIsDrawerOpen: () => {}, // 空函数作为默认dispatch,避免运行时错误 }); const NavBar: ReactFC<{ children?: React.ReactNode }> = ({ children }) => { const [isDrawerOpen, setIsDrawerOpen] = useState(false); return ( <NavContext.Provider value={{ isDrawerOpen, setIsDrawerOpen }}> <ToolBar /> {children} </NavContext.Provider> ); };
这样useContext(NavContext)返回的类型就是确定的NavContextType,解构时不会报错。
方案2:使用自定义Hook封装Context(推荐)
创建一个自定义Hook,在内部做null检查,确保组件必须在Provider范围内使用:
// 在NavBar.tsx中添加自定义Hook export const useNavContext = () => { const context = useContext(NavContext); if (!context) { throw new Error("useNavContext必须在NavContext.Provider内部使用"); } return context; };
然后在ToolBar中使用这个Hook:
import { useNavContext } from "./NavBar"; const ToolBar = () => { // 直接解构,无需担心null const { isDrawerOpen, setIsDrawerOpen } = useNavContext(); return ( // 组件内容 ); };
这种方式既保证了类型安全,又能在错误使用时给出清晰的报错信息。
方案3:非空断言(不推荐)
如果能确保ToolBar永远在NavContext.Provider内部渲染,可以用非空断言!告诉TypeScript值不会为null:
const { isDrawerOpen, setIsDrawerOpen } = useContext(NavContext)!;
但这种方式有风险,如果后续代码不小心把ToolBar移到Provider外,会触发运行时错误。
额外注意
原NavBar组件的类型定义有语法错误,const NavBar: :ReactFC多了一个冒号,应该修正为const NavBar: ReactFC<{ children?: React.ReactNode }>。
内容的提问来源于stack exchange,提问作者Pawan
相关产品推荐
相关产品推荐

