Home > other >  React Context not getting updated on first click
React Context not getting updated on first click

Time:06-04

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.

enter image description here enter image description here

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

  • Related