강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

개미님의 프로필 이미지
개미

작성한 질문수

Next + React Query로 SNS 서비스 만들기

팔로우/언팔로우 optimistic update

팔로우 추천 목록이 빈 배열로 들어옵니다.

작성

·

15

0

안녕하세요.

팔로우 추천 API는 팔로워 수가 많은 순으로 최대 3명을 가져오도록 되어 있는 것으로 알고 있습니다.

현재 발생하는 현상으로는 회원가입한 유저가 없는 경우에 기존 유저에게 추천 목록이 빈 배열로 나타납니다.

그런데 회원가입 후 로그인하면 추천 목록에 로그인한 본인 아이디가 뜨고, 로그아웃 후 기존 유저 A로 로그인하면 이전에 회원가입한 유저 아이디가 추천 목록에 나타납니다.

기존 유저 A가 그 회원가입 한 유저를 팔로우한 상태에서, 다른 기존 유저 B로 로그인하면 A가 팔로우했던 아이디가 추천 목록에서 사라져 있습니다.

팔로우나 언팔로우 기능을 사용할 때 데이터는 정상적으로 들어오는 것으로 확인되고, 팔로워가 있는 아이디가 추천 목록에 나타나야 하는데 빈 배열로 표시됩니다.

어느 부분을 점검해야 문제를 정확히 파악할 수 있을지 감이 잡히지 않아 질문 남겨봅니다..!

스크린샷 2025-09-28 오후 8.17.13.png.webp
import { MouseEventHandler } from "react";
import { User } from "@/model/User";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useSession } from "next-auth/react";

type Props = {
  user: User;
};

export default function FollowRecommend({ user }: Props) {
  const queryClient = useQueryClient();
  const { data: session } = useSession();
  const followed = !!user.Followers?.find((v) => v.id === session?.user?.id);

  // 팔로우
  const follow = useMutation({
    // 호출 시마다 userId를 전달
    mutationFn: (userId: string) => {
      return fetch(
        `${process.env.NEXT_PUBLIC_BASE_URL}/api/users/${userId}/follow`,
        {
          method: "POST",
          credentials: "include",
        },
      );
    },
    onMutate: (userId: string) => {
      const data: User[] | undefined = queryClient.getQueryData([
        "users",
        "followRecommends",
      ]);
      if (data) {
        // 내가 팔로우 하는 대상
        // User 배열 중에 팔로우 버튼을 누른 대상의 userId를 찾아서 그 유저의 Followers 수정
        const index = data.findIndex((users) => users.id === userId);
        const shallow = [...data];
        shallow[index] = {
          ...shallow[index],
          Followers: [{ id: session?.user?.id as string }],
          _count: {
            ...shallow[index]._count,
            Followers: shallow[index]._count.Followers + 1,
          },
        };
        queryClient.setQueryData(["users", "followRecommends"], shallow);
      }
    },
    onError: (error, userId: string) => {
      console.error("팔로우/언팔로우 에러:", error);
      console.log("실패한 userId:", userId);
      const data: User[] | undefined = queryClient.getQueryData([
        "users",
        "followRecommends",
      ]);
      if (data) {
        const index = data.findIndex((users) => users.id === userId);
        const shallow = [...data];
        shallow[index] = {
          ...shallow[index],
          // 내 아이디가 대상 유저의 팔로워 목록에서 빠져야함
          Followers: shallow[index].Followers.filter(
            (f) => f.id !== (session?.user?.id as string),
          ),
          _count: {
            ...shallow[index]._count,
            Followers: shallow[index]._count.Followers - 1,
          },
        };
        queryClient.setQueryData(["users", "followRecommends"], shallow);
      }
    },
  });

  // 팔로우 끊기
  const unfollow = useMutation({
    mutationFn: (userId: string) => {
      return fetch(
        `${process.env.NEXT_PUBLIC_BASE_URL}/api/users/${userId}/follow`,
        {
          method: "DELETE",
          credentials: "include",
        },
      );
    },
    onMutate: (userId: string) => {
      const data: User[] | undefined = queryClient.getQueryData([
        "users",
        "followRecommends",
      ]);
      if (data) {
        const index = data.findIndex((users) => users.id === userId);
        const shallow = [...data];
        shallow[index] = {
          ...shallow[index],
          Followers: shallow[index].Followers.filter(
            (f) => f.id !== (session?.user?.id as string),
          ),
          _count: {
            ...shallow[index]._count,
            Followers: shallow[index]._count.Followers - 1,
          },
        };
        queryClient.setQueryData(["users", "followRecommends"], shallow);
      }
    },
    onError: (error, userId: string) => {
      const data: User[] | undefined = queryClient.getQueryData([
        "users",
        "followRecommends",
      ]);
      if (data) {
        const index = data.findIndex((users) => users.id === userId);
        const shallow = [...data];
        shallow[index] = {
          ...shallow[index],
          Followers: [{ id: session?.user?.id as string }],
          _count: {
            ...shallow[index]._count,
            Followers: shallow[index]._count.Followers + 1,
          },
        };
        queryClient.setQueryData(["users", "followRecommends"], shallow);
      }
    },
  });

  const onFollow: MouseEventHandler<HTMLButtonElement> = (e) => {
    e.stopPropagation();
    e.preventDefault();
    if (followed) {
      console.log("언팔로우");
      unfollow.mutate(user.id);
    } else {
      console.log("팔로우");
      follow.mutate(user.id);
    }
  };

 

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

로그인 로그아웃 시 팔로우 추천 목록이 갱신되고 있는지를 먼저 확인해야할 것 같습니다.

개미님의 프로필 이미지
개미

작성한 질문수

질문하기