Hi I am trying to learn and implement react context. I have encountered a bug when tryin to update user context.
I have a login page and when a user logs in, the email address and the user name should be updated in the user context.
When I click on submit, null information is stored in the context. But, when I click on submit the second time, I can see that the context is getting updated.
authentication.component.jsx
import Navigation from "../navigation/navigation.component";
import { Button, InputGroup, Form } from "react-bootstrap";
import { UserContext, setUser, setEmail } from "../../contexts/user.context";
import { useContext, useEffect, useState } from "react";
import axios from "axios";
import React from "react";
import "./authentication.styles.scss";
const UserLogon = () => {
const { setUser, setEmail } = useContext(UserContext);
const [emailAddr, setEmailAddr] = useState("");
const [password, setPassword] = useState("");
useEffect(() => {
//console.log(emailAddr);
}, [emailAddr, password]);
const updateFormData = () => {
setEmailAddr(emailAddr);
setPassword(password);
console.log("updated");
console.log(emailAddr);
console.log(password);
};
const saveEmail = (event) => {
setEmailAddr(event.target.value);
//console.log(emailAddr);
};
const savePassword = (event) => {
setPassword(event.target.value);
//console.log(password);
};
const verifyUserHandler = (event) => {
event.preventDefault();
const baseURL = `http://localhost:4000/verify_user?email=${emailAddr}&password=${password}`;
axios
.post(baseURL)
.then((response) => {
//console.log("User verified");
if (response.data[2] === "verified") {
console.log("user verified");
var email = response.data[0];
var name = response.data[1];
console.log("email: ", email);
console.log("name: ", name);
setEmail(email);
setUser(name);
} else {
console.log("user auth error");
}
})
.catch((e) => {
console.log(e);
});
};
return (
<div className="auth-container">
<div className="auth-login">
<div className="login-info">
<Form>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control
type="email"
placeholder="Enter email"
onChange={saveEmail}
/>
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Password"
onChange={savePassword}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Check me out" />
</Form.Group>
<Button variant="primary" type="submit" onClick={verifyUserHandler}>
Submit
</Button>
</Form>
</div>
</div>
</div>
);
};
export default UserLogon;
user.context.jsx
import { createContext, useState, useEffect } from "react";
export const UserContext = createContext({
currentUser: null,
setCurrentUser: () => null,
userEmail: null,
setUserEmail: () => null,
});
export const UserProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [userEmail, setUserEmail] = useState(null);
const setUser = (user) => {
console.log("USER: user context before", currentUser);
setCurrentUser(user);
console.log("USER: user context after", currentUser);
};
const setEmail = (email) => {
console.log("EMAIL: user context before", userEmail);
setUserEmail(email);
console.log("EMAIL: user context after", userEmail);
};
const value = { setUser, setEmail, currentUser, userEmail };
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};
Any help is appreciated. thank you.
CodePudding user response:
Try removing the intitial values from createContext. I think it might be causing your issue.
import { createContext, useState, useEffect } from "react";
export const UserContext = createContext();
export const UserProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [userEmail, setUserEmail] = useState(null);
const setUser = (user) => {
setCurrentUser(user);
console.log(currentUser);
};
const setEmail = (email) => {
setUserEmail(email);
console.log(userEmail);
};
const value = { setUser, setEmail, currentUser, userEmail };
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};
CodePudding user response:
The React state setter function is async which means that at the moment you console.log
it's not yet updated in your state : )
Try this to validate:
const setUser = (user) => {
setCurrentUser(user)
console.log({ currentUser, user })
// To better debug wrap vars in { }
}
const setEmail = (email) => {
setUserEmail(email)
console.log({ userEmail, email })
}
More info from docs: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous