위와 같은 상황에서 같은 쿼리키를 가지고 관리되고 있는 리뷰 데이터들의 목록이 있을때 이것에 대해 최신순/추천순 정렬을 구현하는 좋은 방법이 뭐가 있을지 고민해 보다가 query 내에서 select 를 이용하는 방법을 시도해 보았다.
const { data: reviews, isLoading: reviewLoading } = useQuery({
queryKey: ['reviews', placeId],
queryFn: () => getReviewsByPlaceIdrpc(placeId),
enabled: !!placeId,
select: (data) => {
const recentOrder = _.orderBy(data, 'created_at', 'desc');
const likesOrder = _.orderBy(data, 'likes_count', 'desc');
return { recentOrder, likesOrder };
},
});
이 부분이 해당 코드인데 받아온 data를 가지고 두가지 변수명으로 따로 저장하여 리턴하고 있다.
recentOrder 는 lodash를 이용해 최신순 정렬을 하고 있고, likesOrder 는 likes_count를 이용해 추천순 정렬을 하고 있다.
select 옵션을 적극적으로 사용해본 것이 처음이라 사용에 조금은 헤멨는데, data대신에 내가 붙인 reviews라는 이름의 객체 안에 recentOrder와 likesOrder 가 생성되어 있는 것을 확인하였다.
즉, 최신순 정렬된 데이터에 접근하고 싶다면 reviews.recentOrder 로 접근할 수 있는 것이다.
한가지 아쉬운 점은 select로 가공하기 이전의 '원본' 데이터에 접근할 방법을 아직 찾지 못하였다는 것이다. select 함수 안에서 원본도 따로 리턴해준다면 될 일이지만 아무래도 조금 번거롭게 느껴진다. 가장 바랐던 것은 reviews 로 그냥 원본에 접근하고 reviews.isLoading 이런 식으로 가공한 데이터에 접근하는 것인데 나중에 알게 되면 꼭 follow-up 을 적어둘 생각이다.
로그인 한 사용자의 uid가 어떤 게시글 작성자의 uid 와 일치할 때만 삭제버튼을 노출시켜야 하는 상황을 생각해보자.
먼저 boolean 값을 가지는 변수를 만들어서 이를 기반으로 tailwind 속성을 동적으로 변화시키는 방법을 생각해 볼 수 있을 것이다.
const { userId: currentUserId } = useSelector(
(state: RootState) => state.auth,
);
const showDelBtn = comment.user_id == currentUserId ? true : false;
이렇게 리덕스 상태로 관리되고 있는 현재 로그인한 사용자의 uid 와 게시글의 uid 를 비교해서 일치하면 true, 일치하지 않으면 false 값을 가지는 변수를 만든다.
그리고 나서
<div
className={`flex flex-col gap-3 items-end mr-6
${ showDelBtn ? '' : 'hidden'}`}
>
<button
className={`border w-7 border-primary text-primary`}
onClick={deleteBtnHandler.bind(null, comment.id)}
>
X
</button>
</div>
위 코드처럼 className 을 중괄호로 감싸고 템플릿 리터럴로 바꾼 다음 삼항연산자를 사용하면 의도대로 동작하게 된다.
styled-components로 비슷한 로직을 작성했을 때는 styled-components에 넘겨줄 props 에 대한 type 지정을 따로 해줬어야 했는데 Tailwind 에서는 정말 간단하게 구현이 가능해서 이 부분만큼은 확실하게 Tailwind의 우세라고 느껴진다.