I'm trying to keep a live state of either the user is signed-in or not, so I can either show him or not, specific elements in the components. Using this code it's supposed to console.log(0)
and then console.log(1)
, but it actually throws an error Cannot read properties of undefined
.
./addons/Signed.js:
import { useState, createContext } from "react";
export const SignedContext = createContext();
export default function SignedProvider(props) {
const [SignedIn, setSignedIn] = useState(0);
return (
<SignedContext.Provider value={{ SignedIn, setSignedIn }}>
{props.children}
</SignedContext.Provider>
);
}
./screens/Profile.js:
import { useContext } from "react";
import SignedContext from "../addons/Signed";
...
const ProfileScreen = () => {
const { SignedIn, setSignedIn } = useContext(SignedContext);
console.log(SignedIn);
setSignedIn(1);
console.log(SignedIn);
...
}
...
CodePudding user response:
You are using a named export
for SignedContext
but using a default import
in Profile
. Thus, you must use curly braces for your import. The following should change your issue.
import { SignedContext } from ".../addons/Signed"
Edit: If ProfileScreen
is not a child of SignedContext.Provider
, then this will not work. The general workflow is documented here. Hence, if ProfileScreen
is not a child of the Provider, the context won't be available to it.
The ususal way to do this, is to define the context provider as a top level element in your app, if you want the context to be available at a global level in your application.
function App = () => {
const [signedIn, setSignedIn] = useState(0)
const contextValue = React.useMemo(() => ({signedIn, setSignedIn}), [singedIn])
// your application structure must be wrapped inside here.
// as an example I have only used ProfileScreen.
// Usually this is your root stack.
return (
<SignedContext.Provider value ={contextValue}>
<ProfileScreen />
</SignedContext.Provider>
)
}