React Context 在第一次点击时没有得到更新

React Context not getting updated on first click

您好,我正在尝试学习和实施 React 上下文。我在尝试更新用户上下文时遇到了一个错误。

我有一个登录页面,当用户登录时,电子邮件地址和用户名应该在用户上下文中更新。

当我点击提交时,空信息存储在上下文中。但是,当我第二次点击提交时,我可以看到上下文正在更新。

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>;
};

感谢任何帮助。 谢谢。

尝试从 createContext 中删除初始值。我认为这可能会导致您的问题。

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>;
};

React 状态 setter 函数是异步的,这意味着目前您 console.log 它尚未在您的状态中更新:)

试试这个来验证:


const setUser = (user) => {
  setCurrentUser(user)
  console.log({ currentUser, user })
  // To better debug wrap vars in { }
}

const setEmail = (email) => {
  setUserEmail(email)
  console.log({ userEmail, email })
}

来自文档的更多信息:https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

将 useEffect 控制台日志添加到上下文提供程序以检查状态何时发生变化。

  useEffect(() => {
   console.log("User", currentUser);
   console.log("Email", userEmail);
  }, [currentUser, userEmail]);

正如您从 here 中看到的,它工作正常