Appels API illimités déclenchés par UseEffect
P粉501683874
P粉501683874 2023-09-20 20:50:56
0
1
516

J'ai construit un projet MERN où le composant FrindListWidget est appelé sous 2 conditions.

  1. S'il s'agit de la liste d'amis de l'utilisateur, le widget est rendu et le statut dans Redux user.friends est mis à jour.
  2. S'il s'agit d'un autre utilisateur, seul le widget sera rendu. L'état Redux n'est pas mis à jour.

Tous les Friend 还包含一个 ,它将添加或删除 Friend. Apparemment, tout fonctionnait bien jusqu'à ce que je vérifie l'onglet Réseau dans les outils de développement Chrome. J'ai détecté friends 被无限次调用。为了说清楚,我写了console.log("friends",friends);. Oui, cela a été enregistré à plusieurs reprises. Je partage le code suivant :

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 n'est qu'une méthode axios :

export const userRequest = axios.create({
  baseURL: BASE_URL,
  headers: { token: `Bearer ${token}` },
});

J'ai essayé de supprimer la dépendance dans le hook useEffect :

useEffect(() => {
    getFriends();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

Cependant, il n'est rendu qu'une seule fois. Il n'affichera pas les mises à jour via pendant l'exécution. Je dois recharger la fenêtre pour voir les mises à jour.

P粉501683874
P粉501683874

répondre à tous(1)
P粉156532706

Je suppose que vous appelez la fonction getFriends() qui met à jour la liste d'utilisateurs que vous avez injectée dans useEffect, par conséquent, en faisant en sorte que useEffect se mette à jour un nombre infini de fois, essayez de rendre votre useEffect dépendant d'une autre valeur.

useEffect(() => {
    getFriends();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [userId]);

Pour ce cas, j'utilise personnellement réagir-query et j'utilise l'attribut activé pour décider quand appeler à nouveau l'API. Cependant, il y a quelque chose qui ne va vraiment pas avec votre logique et je ne peux pas le comprendre, si vous parvenez à créer un requête réutilisable minimale utilisant une plateforme comme CodeSandBox Exemples de problèmes récurrents afin que nous puissions mieux vous aider.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal