You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React珠宝店应用用户在线状态无法实时更新问题求助

问题描述

用React开发了一个珠宝店应用,包含管理员和客户两种角色。管理员可查看所有用户的在线/离线状态表格,通过给每个客户设置active属性实现:登录成功时active设为1(在线),登出时设为0(离线)。

目前的问题是:用户登录/登出后,在线状态列不会自动更新,必须手动刷新页面才能看到最新状态,确定问题出在前端但找不到具体位置。


相关代码

登录页面代码

import axios from "axios";
import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";

export default function Login() {
  const navigate = useNavigate();
  const [customer, setCustomer] = useState({
    email: "",
    password: "",
  });

  const [onlineusers, setOnline] = useState([]); // 用于追踪在线/离线状态的状态

  useEffect(() => {
    // 组件挂载时加载在线/离线状态
    loadOnlineStatus();
  }, []);

  const { email, password } = customer;

  const onInputChange = (e) => {
    setCustomer({ ...customer, [e.target.name]: e.target.value });
  };

  const loadOnlineStatus = async () => {
    // try {
      const response = await axios.get("http://localhost:8080/customers");
      setOnline(response.data);
    // } catch (error) {
    //   console.error("Error loading online status:", error);
    // }
  };

  const onSubmit = async (e) => {
    e.preventDefault();
  
    try {
      const response = await axios.get(
        `http://localhost:8080/customerEmail?email=${email}&password=${password}`
      );
  
      const loggedInCustomer = response.data;
  
      if (loggedInCustomer) {
        console.log("Login successful:", loggedInCustomer);

        await axios.put(`http://localhost:8080/customeron/${email}`);
        loadOnlineStatus();

        // 存储邮箱
        localStorage.setItem('loggedInEmail', email);
        const role = await axios.get(
            `http://localhost:8080/role?email=${email}&password=${password}`
        );

        if (role.data==="ADMIN") {
          navigate("/admin");
        } else {
          navigate("/customer");
        }
      } else {
        console.error("Login failed");
      }
    } catch (error) {
      console.error("Error during login:", error);
    }
  };
  

  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6 offset-md-3 border rounded p-4 mt-2 shadow">
          <h2 className="text-center m-4">Log In</h2>

          <form onSubmit={(e) => onSubmit(e)}>
            <div className="mb-3">
              <label htmlFor="Email" className="form-label">
                E-mail
              </label>
              <input
                type="text"
                className="form-control"
                placeholder="Enter your e-mail address"
                name="email"
                value={email}
                onChange={(e) => onInputChange(e)}
              />
            </div>
            <div className="mb-3">
              <label htmlFor="Password" className="form-label">
                Password
              </label>
              <input
                type="password" 
                className="form-control"
                placeholder="Enter your password"
                name="password"
                value={password}
                onChange={(e) => onInputChange(e)}
              />
            </div>

            <button type="submit" className="btn btn-outline-danger mx-2">
              Log In
            </button>
            <Link className="btn btn-outline-danger mx-2" to="/register">
              Sign Up
            </Link>
          </form>
        </div>
      </div>
    </div>
  );
}

在线用户页面代码

import React, { useEffect, useState } from "react";
import axios from "axios";
import { Link } from "react-router-dom";

export default function OnlineUsers() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    loadUsers();
  }, []);

  const loadUsers = async () => {
    const result = await axios.get("http://localhost:8080/customers");
    setUsers(result.data);
  };

  return (
    <div className="container">
      <div className="py-4">
        <table className="table border shadow">
          <thead>
            <tr>
              <th scope="col">ID</th>
              <th scope="col">Name</th>
              <th scope="col">Username</th>
              <th scope="col">Email</th>
              <th scope="col">Online Activity</th>
            </tr>
          </thead>
          <tbody>
            {users.map((user, index) => (
              <tr>
                <th scope="row" key={index}>
                  {index + 1}
                </th>
                <td>{user.name}</td>
                <td>{user.username}</td>
                <td>{user.email}</td>
                <td>{user.activ===0 ? "Offline" : "Online"}</td>
              </tr>
            ))}
          </tbody>
        </table>
        <Link
          className="btn btn-outline-primary mx-2"
          to={`/admin`}
        >
          Back
        </Link>
      </div>
    </div>
  );
}

后端控制器函数

@GetMapping("/customers")
List<Customer> getAllCustomers() {
    return customerService.findAll();
}

问题原因与解决方案

问题原因

OnlineUsers组件的useEffect依赖项为空数组,这意味着组件只会在首次挂载时调用一次loadUsers,之后不管后端的用户在线状态如何变化,组件都不会重新请求数据更新状态。

另外,登录页面中调用的loadOnlineStatus只是更新了当前组件的onlineusers状态,但登录后会跳转到管理员/客户页面,这个状态不会同步到OnlineUsers组件,所以也起不到更新作用。

解决方案

方案1:定时刷新用户数据

在OnlineUsers组件中添加定时器,定期请求后端获取最新的用户在线状态,实现自动更新:

import React, { useEffect, useState } from "react";
import axios from "axios";
import { Link } from "react-router-dom";

export default function OnlineUsers() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    // 首次加载
    loadUsers();
    // 设置定时器,每5秒刷新一次
    const interval = setInterval(() => {
      loadUsers();
    }, 5000);
    // 组件卸载时清理定时器
    return () => clearInterval(interval);
  }, []);

  const loadUsers = async () => {
    const result = await axios.get("http://localhost:8080/customers");
    setUsers(result.data);
  };

  // 其余代码不变...
}

方案2:监听路由变化刷新数据

如果希望用户切换到OnlineUsers页面时才刷新数据,可以监听路由变化,每次进入页面时重新加载:

import React, { useEffect, useState } from "react";
import axios from "axios";
import { Link, useLocation } from "react-router-dom";

export default function OnlineUsers() {
  const [users, setUsers] = useState([]);
  const location = useLocation(); // 获取当前路由信息

  useEffect(() => {
    loadUsers();
  }, [location]); // 路由变化时重新加载数据

  const loadUsers = async () => {
    const result = await axios.get("http://localhost:8080/customers");
    setUsers(result.data);
  };

  // 其余代码不变...
}

方案3:使用状态管理(进阶)

如果应用规模较大,可以使用React Context或Redux来全局管理用户在线状态,登录/登出时直接更新全局状态,OnlineUsers组件订阅全局状态变化,实现实时更新。这种方式比定时请求更高效,适合复杂场景。


内容的提问来源于stack exchange,提问作者ruscanca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 03:52:35