I built a MERN project where the component FrindListWidget
is called under 2 conditions.
user.friends
will be updated. Each Friend
also contains a
, which will add or remove Friend
.
Apparently, everything was working fine until I checked the Network tab in Chrome Developer Tools. I detected that friends
was called an infinite number of times. To make it clear, I wrote console.log("friends",friends);
. Yes, it has been recorded numerous times.
I share the following code:
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 [friends, setFriends] = useState([]); const user = useSelector((state) => state.user); const getFriends = async () => { const res = await userRequest.get(`/users/${userId}/friends`); const data = await res.data; if (user._id === userId) { dispatch(setUsersFriends({ friends: data })); setFriends(data); } else { setFriends(data); } }; useEffect(() => { getFriends(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [user, userId]); console.log("friends", friends); //This is being logged for infinite times 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"> {friends.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;
Friend.jsx
//other mui imports import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { userRequest } from "../../requestMethod"; import { setFriends } from "../../Redux/Slices/authSlice"; import { FlexBetween } from "../StyledComponent/FlexBetween"; import UserImage from "../StyledComponent/UserImage"; const Friend = ({ friendId, name, location, userPicturePath }) => { const dispatch = useDispatch(); const navigate = useNavigate(); const { _id } = useSelector((state) => state.user); const friends = useSelector((state) => state.user.friends); const { palette } = useTheme(); const primaryLight = palette.primary.light; const primaryDark = palette.primary.dark; const main = palette.neutral.main; const medium = palette.neutral.medium; const isFriend = friends.find((friend) => friend._id === friendId); const isUser = friendId === _id; const patchFriend = async () => { const res = await userRequest.patch(`/users/${_id}/${friendId}`); const data = await res.data; dispatch(setFriends({ friends: data })); }; return ( <FlexBetween> <FlexBetween gap="1rem"> <UserImage image={userPicturePath} size="55px" /> <Box onClick={() => { navigate(`/profile/${friendId}`); navigate(0); }} > <Typography color={main} variant="h5" fontWeight="500" sx={{ "&:hover": { color: palette.primary.light, cursor: "pointer", }, }} > {name} </Typography> <Typography color={medium} fontSize="0.75rem"> {location} </Typography> </Box> </FlexBetween> {!isUser && ( <IconButton onClick={() => patchFriend()} sx={{ backgroundColor: primaryLight, p: "0.6rem" }} > {isFriend ? ( <PersonRemoveOutlined sx={{ color: primaryDark }} /> ) : ( <PersonAddOutlined sx={{ color: primaryDark }} /> )} </IconButton> )} </FlexBetween> ); }; export default Friend;
userRequest is just an axios method:
export const userRequest = axios.create({ baseURL: BASE_URL, headers: { token: `Bearer ${token}` }, });
I tried removing the dependency in the useEffect hook:
useEffect(() => { getFriends(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []);
However, it only renders once. It will not show updates via
at runtime. I have to reload the window to see the update.
I assume you are calling the getFriends() function which updates the list of users you injected in useEffect, therefore, making useEffect update itself infinitely, try to make your useEffect dependent on another value.
For this case, I personally use react-query and use the enabled attribute to decide when to call the API again, however, there is something seriously wrong with your logic and I can't understand it, if you are able to create one using a platform like CodeSandBox Minimum reproducible example of the problem so we can better help you.