As a React starter, I'm trying to achieve state management in my React app, and use useContext
to share login status between components.
I started learning and read this question: >https://stackoverflow.com/questions/54738681/how-to-change-the-value-of-a-context-with-usecontext?r=SearchResults.
I tried what the answer told me -- use useEffect
to update the context's value:
const initContext: GlobalContext = {
login: false,
}
export const globalContext = React.createContext(null)
function App() {
return <globalContext.Provider value={useState(initContext)}>
{useRoutes(router)}
</globalContext.Provider>
}
But when I use ts to do the same thing, I got error
Type '[GlobalContext, Dispatch<SetStateAction>]' is not assignable to type 'null'.
So I tried another way:
const initContext: GlobalContext = {
login: false,
}
export const globalContext = React.createContext(useState(initContext))
function App() {
return <globalContext.Provider value={useState(initContext)}>
{useRoutes(router)}
</globalContext.Provider>
}
then I got another error:
React Hook "useState" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function.
or I've tried export const globalContext = React.createContext()
, and got error Expected 1 arguments, but got 0.
So my question is how I can update the context's value in ts, could someone please help me?
CodePudding user response:
You likely are wanting to provide a non-null default Context value. The useState
hook also returns an array, not an object with a login
boolean property. You want to pass an object with login
as a property.
const initContext: GlobalContext = {
login: false,
}
export const globalContext = React.createContext(initContext); // <-- pass initContext as default value
function App() {
const [login, setLogin] = useState<boolean>(false);
return (
<globalContext.Provider value={{ login }}>
{useRoutes(router)}
</globalContext.Provider>
);
}
Update
If you need to update the login
value then the setLogin
state updater should be passed in the Context value as well.
Example:
interface IGlobalContext {
login: boolean;
setLogin: React.Dispatch<React.SetStateAction<boolean>>;
}
const initContext: IGlobalContext = {
login: false,
setLogin: () => {}
};
const GlobalContext = React.createContext(initContext);
const useGlobalContext = () => React.useContext(GlobalContext);
function App() {
const [login, setLogin] = useState<boolean>(false);
return (
<GlobalContext.Provider value={{ login, setLogin }}>
{useRoutes(router)}
</GlobalContext.Provider>
);
}