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

疑问:该useEffect是否仅在cachedUsers为空时执行?求优化方案

当前写法的问题(无意义,甚至存在逻辑错误)

  1. 冗余的useMemo:cachedUsers只是fsUsers的引用拷贝,没有任何缓存优化价值,反而增加了不必要的计算开销,完全可以直接使用fsUsers。
  2. 错误的useEffect依赖:[!cachedUsers.length]会导致请求被触发两次:
    • 初始时列表为空,!0为true,执行请求;
    • 请求成功后列表有数据,!length变为false,依赖项变化,会再次发起无效请求——这完全违背了“仅在列表为空时执行”的需求。

更优实现方案

根据你的实际需求,分两种场景给出最优写法:

场景1:仅在组件首次挂载且列表为空时请求一次(最常用)

去掉冗余代码,在useEffect内部加长度判断,同时用空依赖确保只执行一次:

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

const GetAllUsers = () => {
  const [fsUsers, setFsUsers] = useState([]);
  const [notFoundErr, setNotFoundErr] = useState("");
  const [loading, toggleLoading] = useState(true);
  const navigate = useNavigate();

  useEffect(() => {
    // 仅当列表为空时发起请求
    if (fsUsers.length !== 0) return;

    const fetchUsers = async () => {
      try {
        toggleLoading(true);
        const res = await axios({
          method: "GET",
          url: "http://localhost:4000/auth/api/firebase/users",
          validateStatus: (status) => status === 200 || status === 404,
        });

        if (res.status === 200) {
          setFsUsers(res.data);
          setNotFoundErr(""); // 请求成功时清空之前的错误信息
        } else if (res.status === 404) {
          setNotFoundErr("No users found.");
        }
      } catch (error) {
        console.error(error);
        navigate("/error500");
      } finally {
        toggleLoading(false);
      }
    };

    fetchUsers();
  }, []); // 空依赖确保仅组件挂载时执行一次

  return [fsUsers, notFoundErr, loading];
};

export default GetAllUsers;

场景2:需要在列表被清空时自动重新请求(比如有清空操作)

保留对列表长度的依赖,确保每当列表变为空时触发请求:

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

const GetAllUsers = () => {
  const [fsUsers, setFsUsers] = useState([]);
  const [notFoundErr, setNotFoundErr] = useState("");
  const [loading, toggleLoading] = useState(true);
  const navigate = useNavigate();

  useEffect(() => {
    // 仅当列表为空时发起请求
    if (fsUsers.length !== 0) return;

    const fetchUsers = async () => {
      try {
        toggleLoading(true);
        const res = await axios({
          method: "GET",
          url: "http://localhost:4000/auth/api/firebase/users",
          validateStatus: (status) => status === 200 || status === 404,
        });

        if (res.status === 200) {
          setFsUsers(res.data);
          setNotFoundErr("");
        } else if (res.status === 404) {
          setNotFoundErr("No users found.");
        }
      } catch (error) {
        console.error(error);
        navigate("/error500");
      } finally {
        toggleLoading(false);
      }
    };

    fetchUsers();
  }, [fsUsers.length]); // 依赖列表长度,长度变为0时触发请求

  return [fsUsers, notFoundErr, loading];
};

export default GetAllUsers;

额外优化点

  • 请求成功时清空错误信息,避免之前的404提示残留;
  • 简化validateStatus的写法,去掉不必要的冗余判断;
  • 去掉res &&判断:axios在validateStatus允许的状态下不会抛出错误,res一定存在。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:10:18