Hello guys so i tried to make global state so the other page can use the state. The problem is i got an error that says:
JavaScript
x
2
1
Login.js:18 Uncaught TypeError: Cannot destructure property 'emailLog' of '(0 , react__WEBPACK_IMPORTED_MODULE_0__.useContext)(...)' as it is undefined.
2
Im doing this because i want the email from user after logged in and pass them to another page so that i can display the logged in user.
App.js:
JavaScript
1
66
66
1
export const EmailUser = React.createContext();
2
3
function App() {
4
Axios.defaults.withCredentials = true;
5
6
const [invoice, setInvoice] = useState("");
7
const [currency, setCurrency] = useState("IDR");
8
const [myFile, setMyFile] = useState("");
9
const [emailLog, setEmailLog] = useState("");
10
11
return (
12
<EmailUser.Provider value={{ emailLog, setEmailLog }}>
13
<div className="App">
14
<BasicExample />
15
<div className="formInput">
16
<form method="POST" encType="multipart/form-data" action="http://localhost:3001/upload">
17
<div className="textUser"></div>
18
19
<input
20
className="inputForm"
21
defaultValue={emailLog}
22
type="email"
23
disabled
24
name="email"
25
/>
26
27
<input className="inputForm" type="number" placeholder="Invoice No" name="InvoiceNo" />
28
29
<input className="inputForm" type="date" name="Invoice_Date" />
30
31
<input className="inputForm" type="text" placeholder="Description" name="Description" />
32
33
<select
34
className="selectBox"
35
name="Currency"
36
onChange={(e) => {
37
setCurrency(e.target.value);
38
}}
39
>
40
<option value="IDR">IDR</option>
41
<option value="USD">USD</option>
42
<option value="YEN">YEN</option>
43
</select>
44
45
<input className="inputForm" type="number" placeholder="Amount" name="Amount" />
46
47
<input
48
className="custom-file-upload"
49
multiple
50
type="file"
51
name="DocumentFile"
52
onChange={(e) => {
53
setMyFile(e.target.value);
54
}}
55
/>
56
57
<button className="btnSubmit">Submit</button>
58
</form>
59
</div>
60
</div>
61
</EmailUser.Provider>
62
);
63
}
64
65
export default App;
66
Login.js
JavaScript
1
97
97
1
const Login = () => {
2
let navigate = useNavigate();
3
4
const { emailLog, setEmailLog } = useContext(EmailUser);
5
const [passwordLog, setPasswordLog] = useState("");
6
7
const [loginStatus, setLoginStatus] = useState("");
8
9
Axios.defaults.withCredentials = true;
10
11
const login = (e) => {
12
e.preventDefault();
13
Axios.post("http://localhost:3001/login", {
14
email: emailLog,
15
password: passwordLog,
16
}).then((response) => {
17
console.log(response);
18
19
if (response.data.message) {
20
alert(response.data.message);
21
} else {
22
setLoginStatus(response.data[0].email);
23
alert("Redirecting");
24
navigate("/home");
25
}
26
});
27
};
28
console.log(emailLog);
29
30
useEffect(() => {
31
Axios.get("http://localhost:3001/login").then((response) => {
32
if (response.data.loggedIn == true) {
33
setLoginStatus(response.data.email[0].email);
34
}
35
});
36
});
37
38
return (
39
<div>
40
<img className="wave" src={Wave} />
41
<img className="wave2" src={WaveV2} />
42
<div className="wrapper">
43
<div className="img">{/* <img src={Background}/> */}</div>
44
45
<div className="register-content">
46
<div className="registerForm">
47
<img src={Avatar} />
48
<h2 className="title">Welcome</h2>
49
<div className="input-div one">
50
<div className="i">
51
<i className="fas fa-user">
52
<GrMail />
53
</i>
54
</div>
55
<div className="div">
56
<input
57
type="email"
58
className="input"
59
placeholder="Email"
60
required
61
onChange={(e) => {
62
setEmailLog(e.target.value);
63
}}
64
/>
65
</div>
66
</div>
67
<div className="input-div pass">
68
<div className="i">
69
<i className="fas fa-lock">
70
<AiFillLock />
71
</i>
72
</div>
73
<div className="div">
74
<input
75
type="password"
76
className="input"
77
placeholder="Password"
78
required
79
onChange={(e) => {
80
setPasswordLog(e.target.value);
81
}}
82
/>
83
</div>
84
</div>
85
<a href="/">Don't have an account ?</a>
86
<button type="submit" className="btn" onClick={login}>
87
Login
88
</button>
89
</div>
90
</div>
91
</div>
92
</div>
93
);
94
};
95
96
export default Login;
97
Advertisement
Answer
EmailUser
context works only with the components that are children of EmailUser.Provider
, and it doesn’t seem to be the case for Login
component. An easy way is to create a separate component, in some EmailUserProvider.js
, like so:
JavaScript
1
11
11
1
import {createContext, useState} from "react"
2
export const EmailUser = createContext();
3
export default function EmailUserProvider({children}) {
4
const [emailLog, setEmailLog] = useState("");
5
return (
6
<EmailUser.Provider value={{ emailLog, setEmailLog }}>
7
{children}
8
</EmailUser.Provider>
9
);
10
}
11
And make it wrap all the components that would consume it. If I assume all my components and routes are rendered in App
and want the context to be global, I would do so:
JavaScript
1
4
1
<EmailUserProvider>
2
<App/>
3
</EmailUserProvider>
4