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

MERN项目中FriendListWidget组件useEffect无限调用API问题

问题根源

无限调用friends接口的核心原因是循环触发:

  • 查看自身好友列表时,getFriends会通过dispatch(setUsersFriends)更新Redux中的user.friends,导致user对象发生变化
  • useEffect的依赖包含整个user对象,因此会再次触发getFriends,形成dispatch → user状态变化 → useEffect重跑 → 再次dispatch的无限循环

解决方案

1. 拆分状态逻辑,消除冗余状态

  • 查看自身好友列表时:直接复用Redux中user.friends的数据,不需要维护本地friends状态,避免状态同步冲突
  • 查看他人好友列表时:仅使用本地状态存储数据,避免和Redux状态耦合

2. 优化useEffect依赖项

移除对整个user对象的依赖,仅保留userId作为触发条件:

  • 自身场景:初始加载时调用一次接口,后续好友列表的更新由Friend组件的操作直接更新Redux,自动同步UI
  • 他人场景:仅在userId切换时重新调用接口

修改后的FriendListWidget.jsx代码

// other mui imports
import { WidgetWrapper } from "../../../components/StyledComponent/WidgetWrapper";
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setFriends as setUsersFriends } from "../../../Redux/Slices/authSlice";
import { userRequest } from "../../../requestMethod";

import Friend from "../../../components/Friend";

const FriendListWidget = ({ userId }) => {
  const dispatch = useDispatch();
  const { palette } = useTheme();
  // 仅存储他人的好友列表
  const [otherUserFriends, setOtherUserFriends] = useState([]);
  const user = useSelector((state) => state.user);
  // 自身好友列表直接取Redux数据
  const selfFriends = user.friends || [];

  const getFriends = async () => {
    const res = await userRequest.get(`/users/${userId}/friends`);
    const data = await res.data;
    
    if (user._id === userId) {
      // 仅在切换到自身列表时更新Redux
      dispatch(setUsersFriends({ friends: data }));
    } else {
      setOtherUserFriends(data);
    }
  };

  useEffect(() => {
    getFriends();
  }, [userId]); // 仅依赖userId变化触发

  // 根据场景选择渲染用的好友数据
  const renderFriends = user._id === userId ? selfFriends : otherUserFriends;

  return (
    <WidgetWrapper>
      <Typography
        color={palette.neutral.dark}
        variant="h5"
        fontWeight="500"
        sx={{ mb: "1.5rem" }}
      >
        Friend List
      </Typography>
      <Box display="flex" flexDirection="column" gap="1.5rem">
        {renderFriends.map((friend) => (
          <Friend
            key={friend._id}
            friendId={friend._id}
            name={`${friend.firstName} ${friend.lastName}`}
            subtitle={friend.occupation}
            userPicturePath={friend.picturePath}
          />
        ))}
      </Box>
    </WidgetWrapper>
  );
};

export default FriendListWidget;

3. 保留实时更新能力

Friend组件中的patchFriend方法已经正确通过dispatch(setFriends)更新Redux状态,因此用户点击添加/移除好友后,FriendListWidget会自动获取Redux的最新数据重新渲染,无需手动调用接口,保证实时性。


额外优化建议

  • 为getFriends添加防抖逻辑,避免快速切换用户时多次触发接口请求
  • 增加加载状态组件,在接口请求过程中显示加载提示,提升用户体验

内容的提问来源于stack exchange,提问作者Emdadudl Haque Apu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:15:57