刷新页面后,配置文件详细信息未呈现,数据未存储在状态中

问题描述 投票:0回答:1

我对反应编码非常陌生,我遇到了一个无法解决的问题。

问题是,登录页面后将重定向到个人资料详细信息,登录时工作正常并显示个人资料详细信息,但当我刷新页面时,不会呈现个人资料详细信息。

function ProfileDetails() {
  const {
    profileData,
    loading,
    backendUrl,
    token,
    userId,
    setProfileData,
    setLoading,
  } = useContext(AppContext);


    const fetchProfileData = async () => {
      try {
        setLoading(true); // Start loading
        const { data } = await axios.get(`${backendUrl}/api/user/profile/${userId}`, {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        });
        if (data.success) {
          setProfileData(data.user); // Set profile data in context
         
        }
      } catch (err) {
        toast.error("Error fetching the profile data");
        console.error("Error fetching the data", err);
      } finally {
        setLoading(false); // Stop loading
        console.log("profileData",profileData)
      }
    };

    useEffect(()=>{
      if(token && userId){
        fetchProfileData()
      }
    },[token,userId])

  if (loading) {
    return (
      <div className="flex justify-center items-center h-screen">
        <CircularProgress />
      </div>
    );
  }

  if (!profileData) {
    return <div>No profile data available</div>;
  }

  return profileData && (
    <div
      id="candidate_header"
      className="flex flex-col md:flex-row md:items-end bg-[#f5f7fd] gap-10 md:justify-between pt-20 pb-8 px-5"
    >
      <div id="skills" className="flex flex-wrap gap-2 justify-center md:justify-normal">
        {profileData.skills.map((skill, index) => (
          <p key={index} className="skill-candidatedetails">{skill}</p>
        ))}
      </div>
      <div id="image" className="w-full flex flex-col items-center md:w-1/3">
        <div className="w-16 h-16 bg-gray-100 rounded-full overflow-hidden cursor-pointer">
          <img
            className="w-full h-full object-cover"
            src={profileData.profileImg}
            alt="Profile photo"
          />
        </div>
        <h2 className="text-2xl font-bold my-1 text-center">{profileData.name}</h2>
        <h3 className="text-sm font-normal text-[#1967D2] text-center">
          {profileData.designation}
        </h3>
      </div>
      <div className="md:w-1/3 w-full flex justify-center">
        <button className="ui-btn">Download CV</button>
        <button className="ui-btn">Invite</button>
      </div>
    </div>
  );
}

下面是登录组件代码

// LoginPage.js
import React, { useContext, useState, useEffect } from "react";
import Logo from "./../images/logo.svg";
import axios from "axios";
import { AppContext } from "../AppContext";
import { toast } from "react-toastify";
import { useNavigate } from "react-router-dom";

function LoginPage() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const { backendUrl, setUserId, setToken,setProfileData,profileData } =
    useContext(AppContext);
  const navigate = useNavigate();


  const loginHandler = async (e) => {
    e.preventDefault();
    try {
      const { data } = await axios.post(`${backendUrl}/api/user/login`, {
        email,
        password,
      });
      if (data.success) {
        localStorage.setItem("token", data.token);
        setToken(data.token); 
        axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}`;
        setUserId(data.user._id)
        setProfileData(data.user)
        toast.success("Login Successful");
        
        navigate(`/profile/${data.user._id}`);
      }
    } catch (err) {
      const errorMessage =
        err.response?.data?.message || "An error occurred while logging in";
      toast.error(errorMessage);
      console.log(errorMessage);
    }
  };

  return (
    <form className="min-h-[80vh] flex items-center" onSubmit={loginHandler}>
      <div className="flex flex-col gap-3 m-auto items-start p-8 min-w-[340px] sm:min-w-96 border rounded-xl text-[#5E5E5E] text-sm shadow-lg">
        <img src={Logo} className="mx-auto" />
        <div className="w-full">
          <p>Email</p>
          <input
            className="border border-[#DADADA] rounded w-full p-2 mt-1"
            value={email}
            type="email"
            onChange={(e) => setEmail(e.target.value)}
            required
          />
        </div>
        <div className="w-full">
          <p>Password</p>
          <input
            className="border border-[#DADADA] rounded w-full p-2 mt-1"
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            required
          />
        </div>
        <button className="bg-[#1967D2] text-white w-full py-2 rounded-md text-base">
          Login
        </button>
      </div>
    </form>
  );
}

export default LoginPage;

AppContext代码

const AppContextProvider = (props) => {
  const [token, setToken] = useState(localStorage.getItem("token") || "");
  const [userId, setUserId] = useState("");
  const [profileData, setProfileData] = useState("");
  const [loading, setLoading] = useState(false); // Add loading state
  const backendUrl = import.meta.env.VITE_BACKEND_URL;


  const value = {
    backendUrl,
    setToken,
    userId,
    setUserId,
    loading,
    profileData,
    setProfileData
  };

  return (
    <AppContext.Provider value={value}>{props.children}</AppContext.Provider>
  );
};

我认为问题在于 Profiledata 状态变量在刷新时不保存数据,但如果令牌可用,我正在运行 fetchprofileData 函数。

reactjs react-state
1个回答
0
投票

ProfileDetails组件之所以在刷新页面时没有渲染用户的详细信息,很大程度上是因为这里的这段代码:

useEffect(()=>{
    if(token && userId){
        fetchProfileData()
    }
},[token, userId])

此 useEffect 挂钩的目的是在组件安装时运行其中的代码。这个 useEffect 挂钩会在您登录时运行,因为您正在

loginHandler
函数中设置 userId 的值和令牌状态。但是当您刷新页面时,令牌和 userId 的状态都会丢失。但是,只有令牌保留在本地存储中。我看到您正在从 AppContextProvider 的本地存储中检索它

const [token, setToken] = useState(localStorage.getItem("token") || "");

在这种情况下,token 状态不为空,但 userId 状态为空。 useEffect 中的检查意味着令牌和 userId 状态都必须具有真实值,然后才能运行

fetchProfileData
函数。

为了解决此问题,您可能必须从 useEffect 挂钩中删除 userId 条件,然后仅检查令牌:

useEffect(()=>{
    if(token){
        fetchProfileData()
    }
},[token])

但是,如果存在 userId 对于 useEffect 挂钩运行很重要,那么您可能希望将 userId 值保留在本地存储中,就像您对令牌所做的那样:

const loginHandler = async (e) => {
    e.preventDefault();
    try {
      const { data } = await axios.post(`${backendUrl}/api/user/login`, {
        email,
        password,
      });
      if (data.success) {
        localStorage.setItem("token", data.token);
        localStorage.setItem("userId", data.user._id);
        setToken(data.token); 
        axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}`;
        setUserId(data.user._id)
        setProfileData(data.user)
        toast.success("Login Successful");
        
        navigate(`/profile/${data.user._id}`);
      }
    } catch (err) {
      const errorMessage =
        err.response?.data?.message || "An error occurred while logging in";
      toast.error(errorMessage);
      console.log(errorMessage);
    }
  };

然后您可以在 AppContextProvider 中检索它:

const [userId, setUserId] = useState(localStorage.getItem("userId") || "");

我希望这有助于解决您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.