Typescript 中带有 useContext 的 useState

useState with useContext in Typescript

假设我有一个基本设置来检查用户是否登录:

import { createContext } from "react";
const UserContext = createContext<string | null>(null)
export default UserContext

在我的 App.tsx 中,我想创建一个 useState 挂钩,以便我可以在整个应用程序中管理我的上下文状态:

//Context
const [context, setContext] = useState<string | null>(null)

  <UserContext.Provider value={{context, setContext}}>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </UserContext.Provider>

据我所知,如果我想拒绝访问某些页面,我只需要登录用户的名称,或者将上下文状态设置为 null。现在的问题是打字稿在这里对我大喊大叫,特别是在 Provider 的值中:

Type '{ context: string | null; setContext: 
React.Dispatch<React.SetStateAction<string | null>>; }' is not assignable to type 'string'.ts(2322)

我可以强制转换值如下:

value={{context, setContext} as any}

但这似乎不是一个特别优雅的'typescripty'解决方案。

感谢任何帮助!

您输入的上下文为:

string | null

但随后您为该上下文提供了一个(大约)类型的值:

{ context: string | null, setContext: (newString) => void }

所以如果你想在你的上下文中使用状态 setter,那么它需要是上下文类型的一部分:

const UserContext = createContext<{
  context: string | null,
  setContext: (newValue) => void
}>({
  context: null,
  setContext: () => undefined
})

根据 Alex 的回答,我想出了一个适合我的调整:

type UserContextType = {
     context: string | null,
     setContext: React.Dispatch<React.SetStateAction<string | null>>
 }

const iUserContextState = {
    context: null,
    setContext: () => {}
}

const UserContext = createContext<UserContextType>(iUserContextState)

export default UserContext

然后在App.tsx:

//Context
const [context, setContext] = useState<string | null>(null)

  <UserContext.Provider value={{context, setContext}}>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </UserContext.Provider>