티스토리 뷰

많이 어려워했던 react-Query를 결국 해냈다!

물론 다른 팀원의 코드를 참고했지만 query에 대해 많이 배울 수 있었다.

파일을 나눠 서버 데이터를 요청하는 api파일, 서버 데이터를 받아 가공하는 util파일로 나누어 작업했다


 

API 파일

  • 비동기 함수를 통해 서버로부터 데이터를 요청한다
  • arg는 데이터 정렬을 위한 state와, useSearchParams로 받는 category를 받는다
  • 파이어베이스에서 받은 데이터를 return 해주면 완성!
export async function getMainProducts() {
  const response = await getDocs(query(collection(db, 'product'), orderBy('createdAt', 'desc')));

  const fetchedProducts: ProductType[] = [];
  response?.forEach((doc) => {
    const products = doc.data() as ProductType;
    fetchedProducts.push({ ...products });
  });

  return fetchedProducts;
}

export async function getProducts(selectedTab: boolean, category: string) {
  const response = await getDocs(
    query(
      collection(db, 'product'),
      where('category', '==', category),
      selectedTab ? orderBy('price', 'desc') : orderBy('price', 'asc')
    )
  );
  const fetchedProducts: ProductType[] = [];
  response?.forEach((doc) => {
    const product = doc.data() as ProductType;
    fetchedProducts.push({ ...product });
  });

  return fetchedProducts;
}

 

util 파일

  • 쿼리를 사용하는 곳 queryKey와 queryFn을 넣는다
  • key는 서버에서 받아온 데이터를 전역에서 사용하기 위해 queryFn과 연결해 주는 변수명과 같다(등록, 수정, 삭제 등 뮤테이션을 사용할 때 쿼리키를 이용한다)
  • queryFn은 api에 작성한 비동기 함수를 연결해 주면 완성! (인자값도 동일하게 전달해줘야 한다. 순서도 동일하게!)
export function useGetMainProducts() {
  return useQuery({
    queryKey: ['mainProducts'],
    queryFn: () => getMainProducts()
  });
}

export function useGetProducts(selectedTab: boolean, category: string) {
  return useQuery({
    queryKey: ['products'],
    queryFn: () => getProducts(selectedTab, category)
  });
}

 

QueryData 사용하기

  • query에 저장된 data와 상태변수, 함수 등을 util에 작성한 함수명으로 꺼내주고 사용하면 끝!
  • 인자값은 순서에 맞게 넣어줄 것!
 const [selectedTab, setSelectedTab] = useState(true);

  const params = useSearchParams();
  const category = params.get('category');
  // params - / 기준으로 전달
  // useSearchParams - ? 기준으로 전달

  const { data, isLoading, isError, refetch } = useGetProducts(selectedTab, category!);

  useEffect(() => {
    refetch();
  }, [selectedTab, refetch, category]);

  if (isLoading) {
    return (
      <div className="flex flex-col items-center justify-center h-screen">
        <div>잠시만 기다려 주세요</div>
        <img src="../../../assets/bean.gif" alt="로딩중" />
      </div>
    );
  }

  if (isError) {
    toast.error('데이터를 가져올 수 없습니다');
  }

마지막에 좋아요 기능을 만들고 싶었는데 결국 실패했다ㅠㅠ

파이어베이스는 아무래도 사용량이 적다 보니 테스트하는 것도 한계가 있어서... 나중에 jsonServer를 이용해  다시 만들어보기로... 아래 코드는 아직 정리 중이라 작동되지 않는다. 이후에 좋아요 기능을 꼭 구현해 보고자 나름 내 노력 같은 걸 기록하기 위해 넣은 것이니 구조정도만 참고할 것 

function Like({ item }: { item: ProductType }) {

  // 하트 아이콘 상태
  const [like, setLike] = useState(false);

  // 쿼리 사용 전 임시로 좋아요 테이블 데이터를 담은 상태
  const [likedState, setLikedState] = useState();

  // 유저아이디
  const userId = useAppSelector(userState);
  const dispatch = useAppDispatch();

  useEffect(() => {
    const likedData = async () => {
      const querySnapshot = await getDocs(
        query(collection(db, 'liked'), where('userId', '==', userId), where('ProductId', '==', item.productId))
      );
      const fetchedLiked: any = [];
      querySnapshot.forEach((doc) => {
        const likeDocData = doc.data();
        fetchedLiked.push({ ...likeDocData, id: doc.id });
      });
      setLikedState(fetchedLiked);
    };

    likedData();
  }, []);

  // console.log('likedState', likedState);
  // console.log('userId', userId);

  const addLikedhandler = async (item: ProductType) => {
    if (userId) {
      if (likedState) {
        try {
          const removeLiked = doc(collection(db, 'liked'), likedState);
          await deleteDoc(removeLiked);
          toast.success('찜한 상품이 삭제됐습니다');
          setLike(false);
        } catch (error) {
          console.log('좋아요 삭제 실패', error);
        }
      } else {
        try {
          const liked = {
            userId,
            ...item
          };
          const likedAdd = collection(db, 'liked');
          await addDoc(likedAdd, liked);
          toast.success('찜한 상품이 추가됐습니다');
          setLike(true);
        } catch (error) {
          console.log('좋아요 추가 실패', error);
        }
      }
    }
  };
  return (
    <button onClick={() => addLikedhandler(item)}>
      <IoHeartSharp className={`${like ? 'text-3xl text-rose-500' : 'text-3xl hover:text-rose-500'}`} />
    </button>
  );
}

export default Like;

// 좋아요 리스트를 상품 아이디와 회원 아이디로 필터링해서 데이터를 가져온다
// 데이터가 있으면 삭제 없으면 추가를한다

미주샵 배포 URL

https://shoppy-sage.vercel.app/

 

Miju Food

잠시만 기다려 주세요

shoppy-sage.vercel.app

 

팀프로젝트 Github

https://github.com/sparta-Shoppy/Shoppy

 

GitHub - sparta-Shoppy/Shoppy: Shoppy

Shoppy. Contribute to sparta-Shoppy/Shoppy development by creating an account on GitHub.

github.com

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함