diff --git a/bun.lock b/bun.lock index 60fd9d8..1626306 100644 --- a/bun.lock +++ b/bun.lock @@ -18,6 +18,7 @@ "dependencies": { "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/vite": "^4.1.13", + "@tanstack/react-query": "^5.90.5", "axios": "^1.12.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -297,6 +298,10 @@ "@tailwindcss/vite": ["@tailwindcss/vite@4.1.13", "", { "dependencies": { "@tailwindcss/node": "4.1.13", "@tailwindcss/oxide": "4.1.13", "tailwindcss": "4.1.13" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ=="], + "@tanstack/query-core": ["@tanstack/query-core@5.90.5", "", {}, "sha512-wLamYp7FaDq6ZnNehypKI5fNvxHPfTYylE0m/ZpuuzJfJqhR5Pxg9gvGBHZx4n7J+V5Rg5mZxHHTlv25Zt5u+w=="], + + "@tanstack/react-query": ["@tanstack/react-query@5.90.5", "", { "dependencies": { "@tanstack/query-core": "5.90.5" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-pN+8UWpxZkEJ/Rnnj2v2Sxpx1WFlaa9L6a4UO89p6tTQbeo+m0MS8oYDjbggrR8QcTyjKoYWKS3xJQGr3ExT8Q=="], + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], diff --git a/packages/client/package.json b/packages/client/package.json index 44009f8..d8c6c6a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -12,6 +12,7 @@ "dependencies": { "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/vite": "^4.1.13", + "@tanstack/react-query": "^5.90.5", "axios": "^1.12.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", diff --git a/packages/client/src/components/reviews/ReviewList.tsx b/packages/client/src/components/reviews/ReviewList.tsx index 8872705..749a91e 100644 --- a/packages/client/src/components/reviews/ReviewList.tsx +++ b/packages/client/src/components/reviews/ReviewList.tsx @@ -1,7 +1,7 @@ import axios from 'axios'; -import { useEffect, useState } from 'react'; import Skeleton from 'react-loading-skeleton'; import StarRating from './StarRating'; +import { useQuery } from '@tanstack/react-query'; interface Props { productId: number; @@ -21,30 +21,21 @@ type GetReviewsResponse = { }; const ReviewList = ({ productId }: Props) => { - const [reviewData, setReviewData] = useState(); - const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(''); + const { + data: reviewData, + isLoading, + error, + } = useQuery({ + queryKey: ['reviews', productId], + queryFn: () => fetchReviews(), + }); - const fetchReviews = async ({ productId }: Props) => { - try { - setError(''); - setIsLoading(true); - const { data } = await axios.get( - `/api/products/${productId}/reviews` - ); - setReviewData(data); - } catch (error) { - console.error(error); - setError( - 'Sorry, cannot fetch the reviews at this time, please retry.' - ); - } finally { - setIsLoading(false); - } + const fetchReviews = async () => { + const { data } = await axios.get( + `/api/products/${productId}/reviews` + ); + return data; }; - useEffect(() => { - fetchReviews({ productId }); - }, []); if (isLoading) { return ( @@ -61,7 +52,11 @@ const ReviewList = ({ productId }: Props) => { } if (error) { - return

{error}

; + return ( +

+ Could not fetch reviews, please try again. +

+ ); } return ( diff --git a/packages/client/src/main.tsx b/packages/client/src/main.tsx index 2a5e3dd..2635d4c 100644 --- a/packages/client/src/main.tsx +++ b/packages/client/src/main.tsx @@ -1,11 +1,15 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import 'react-loading-skeleton/dist/skeleton.css'; import './index.css'; import App from './App.tsx'; +const queryClient = new QueryClient(); createRoot(document.getElementById('root')!).render( - + + + );