처음에는 좋아요의 상태를 해당 컴포넌트에서 useState를 처리해서 사용하려 하였다. 하지만 제로초님은 따로 useState로 관리를 하지 않고 서버상태를 직접 바꿔주고 컴포넌트안에서 find로 직접 연산하는 방법을 선택하였다.

내가 처음에 생각한 방법

const [isLiked, setIsLiked] = useState(
    data.Likers.find((v) => me?.id && v.id === me.id)
  );

// 1. like누르면 서버로 mutate를 하고 성공시 state를 업데이트

// 2. UI는 isLiked state를 value로 받음

제로초님의 방법

const likeMutation = useMutation<Post, AxiosError, number>(['post', post.id], likePostAPI, {
    onMutate() {
      if (!me) return;
      queryClient.setQueryData<InfiniteData<Post[]>>('posts', (data) => {
        const found = data?.pages.flat().find((v) => v.id === post.id);
        if (found) {
          found.Likers.push({ id: me.id });
        }
        return {
          pageParams: data?.pageParams || [],
          pages: data?.pages || [],
        };
      });
    },
    onSettled() {
      queryClient.refetchQueries('posts');
    },
  });

const liked = post.Likers.find((v) => me?.id && v.id === me.id);

liked라는 변수를 만들고 mutate시에 서버 상태에 직접 접근해서 값을 변경해주는것을 볼수 있다.

처음에는 내가 사용한 방법이 좀더 직관적이고 연산도 필요없으니 더 좋을것 같다고 생각했지만 좀 더 생각해보니 두번째 방법을 사용하면 더 좋은 장점들이 생기게 된다.

  1. 상태의 동기화
    1. 첫번째 방법을 사용하면 서버상태와 컴포넌트 상태가 동기화가 되지 않게 된다. 따라서 나중에 서버 상태를 사용해야 할때 이런 차이점이 생기게 되고 이는 디버깅을 어렵게 만든다. 두번째 방법을 사용하면 서버상태와 동기화가 되어있으므로 이러한 단점이 사라지게 된다.
  2. 불필요한 상태 생성
    1. like는 서버상태의 값으로 계산될수 있는 값이다 따라서 state를 두어서 처리한다면 파생된 값을 state로 사용해 중복이 되는것이다. 이럴때는 state를 줄여서 상태관리 범위를 줄이도록 하자