강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của ryukmmm
ryukmmm

câu hỏi đã được viết

Tiếp theo + Tạo dịch vụ SNS bằng React Query

Theo dõi/Bỏ theo dõi - Cập nhật lạc quan

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

Đã giải quyết

Viết

·

124

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);
    }
  };

 

reactnext.jsreact-querynext-authmsw

Câu trả lời 1

0

zerocho님의 프로필 이미지
zerocho
Người chia sẻ kiến thức

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

ryukmmm님의 프로필 이미지
ryukmmm
Người đặt câu hỏi

안녕하세요!

로그인 시에는 요청이 304 Not Modified로 들어오고, 로그아웃 시에는 요청 자체가 발생하지 않는 것으로 보아, 갱신이 이루어지지 않고 이전 캐시만 남아 있는 상태인 것 같습니다.

팔로우 추천 함수에는 쿠키를 전달하고 있는데, 어디를 점검해야 팔로우 추천 목록이 정상적으로 갱신될지 확인할 수 있을까요?

zerocho님의 프로필 이미지
zerocho
Người chia sẻ kiến thức

아, 현재 코드 구조상 FollowRecommendSection.tsx의 queryKey가 ['users', 'followRecommends']로 고정되어있어서 유저가 로그인을 했든 안 했든 한 번 쿼리한 결과물이 캐싱되네요. 쿼리 키에 유저 로그인 여부나 유저 아이디같은 것을 추가해서 로그인, 로그아웃 시 쿼리 키가 변하게 만들어서 다시 불러오게끔 해야할 것 같습니다.

ryukmmm님의 프로필 이미지
ryukmmm
Người đặt câu hỏi

아하! 같은 쿼리로 인식되는거군요. 빠른 답변 감사합니다! :)

Hình ảnh hồ sơ của ryukmmm
ryukmmm

câu hỏi đã được viết

Đặt câu hỏi