Lets say I have a basic setup for checking whether a user is logged in or not:
import { createContext } from "react";
const UserContext = createContext<string | null>(null)
export default UserContext
In my App.tsx I want to create a useState hook so that I can manage the state of my context throughout my application:
//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>
So as far as I can see I'll only ever need either the name of the logged in user, or set the state of the context to null if I want to deny access to certain pages. Now the issue is that typescript is yelling at me here, specifically in the value of the Provider:
Type '{ context: string | null; setContext:
React.Dispatch<React.SetStateAction<string | null>>; }' is not assignable to type 'string'.ts(2322)
I can force cast the value as follows:
value={{context, setContext} as any}
But that doesn't seem like a particularly elegant 'typescripty' solution.
Any help is appreciated!
CodePudding user response:
You've typed your context as:
string | null
But then you provide a value for that context of (approxiamately) type:
{ context: string | null, setContext: (newString) => void }
So if you want the state setter in your context, then it needs to be part of the context's type:
const UserContext = createContext<{
context: string | null,
setContext: (newValue) => void
}>({
context: null,
setContext: () => undefined
})
CodePudding user response:
Based on Alex's answer I came up with a tweak that works for me:
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
And then in 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>