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
相关产品推荐
相关产品推荐

