diff --git a/app/package-lock.json b/app/package-lock.json index 891492b..f308ace 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -37,6 +37,7 @@ "react-dom": "^18", "react-icons": "^5.3.0", "sonner": "^1.7.0", + "swr": "^2.2.5", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7" }, @@ -10268,6 +10269,19 @@ "url": "https://opencollective.com/svgo" } }, + "node_modules/swr": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", + "integrity": "sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==", + "license": "MIT", + "dependencies": { + "client-only": "^0.0.1", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/tailwind-merge": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz", @@ -10860,6 +10874,15 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", diff --git a/app/package.json b/app/package.json index ae7c78c..cfef026 100755 --- a/app/package.json +++ b/app/package.json @@ -41,6 +41,7 @@ "react-dom": "^18", "react-icons": "^5.3.0", "sonner": "^1.7.0", + "swr": "^2.2.5", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7" }, diff --git a/app/src/components/view/ranking/ImageList.tsx b/app/src/components/view/ranking/ImageList.tsx index 1aa5797..5b1e5f1 100644 --- a/app/src/components/view/ranking/ImageList.tsx +++ b/app/src/components/view/ranking/ImageList.tsx @@ -1,8 +1,9 @@ -import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; +import { fetcher } from "@/functions/fetcher"; import type { ScoreDetail } from "@/types"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { VscListOrdered } from "react-icons/vsc"; +import useSWR from "swr"; import { LoadingSpinner } from "../LoadingSpinner"; type ImageListProps = { @@ -15,31 +16,19 @@ const MODE = { } as const; export const ImageList = ({ setMode }: ImageListProps) => { - const [isLoading, setIsLoading] = useState(true); + const { data, error, isLoading } = useSWR("/api/score/imagelist", fetcher); - const [scoreDetails, setScoreDetails] = useState([]); - useEffect(() => { - const fetchData = () => { - setIsLoading(true); - return fetch("/api/score/imagelist") - .then((response) => { - if (!response.ok) { - throw new Error("Failed to fetch data"); - } - return response.json(); - }) - .then((result) => setScoreDetails(result)) - .catch((error) => console.error("Error fetching data:", error)) - .finally(() => setIsLoading(false)); - }; - - fetchData(); - }, []); + // アサーションすみません + const scoreDetails = data as ScoreDetail[]; if (isLoading) { return ; } + if (error) { + console.error("Failed to fetch data"); + } + return (
diff --git a/app/src/components/view/ranking/RankingListAll.tsx b/app/src/components/view/ranking/RankingListAll.tsx index 40f2558..f2eda68 100644 --- a/app/src/components/view/ranking/RankingListAll.tsx +++ b/app/src/components/view/ranking/RankingListAll.tsx @@ -1,30 +1,15 @@ import { Card } from "@/components/ui/card"; +import { fetcher } from "@/functions/fetcher"; import type { RankingScores } from "@/types"; -import { useEffect, useState } from "react"; +import useSWR from "swr"; import { LoadingSpinner } from "../LoadingSpinner"; -export default function RankingListAll() { - const [data, setData] = useState([]); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - const fetchData = () => { - setIsLoading(true); - return fetch("/api/score/all") - .then((response) => { - if (!response.ok) { - throw new Error("Failed to fetch data"); - } - return response.json(); - }) - .then((result) => setData(result)) - .catch((error) => console.error("Error fetching data:", error)) - .finally(() => setIsLoading(false)); - }; - - fetchData(); - }, []); +export default function RankingListWeekly() { + const { data, error, isLoading } = useSWR("/api/score/all", fetcher); + if (error) { + console.error("Failed to fetch data"); + } if (isLoading) { return ; } diff --git a/app/src/components/view/ranking/RankingListWeekly.tsx b/app/src/components/view/ranking/RankingListWeekly.tsx index 4cbceb9..df063a2 100644 --- a/app/src/components/view/ranking/RankingListWeekly.tsx +++ b/app/src/components/view/ranking/RankingListWeekly.tsx @@ -1,29 +1,15 @@ import { Card } from "@/components/ui/card"; +import { fetcher } from "@/functions/fetcher"; import type { RankingScores } from "@/types"; -import { useEffect, useState } from "react"; +import useSWR from "swr"; import { LoadingSpinner } from "../LoadingSpinner"; export default function RankingListWeekly() { - const [data, setData] = useState([]); - const [isLoading, setIsLoading] = useState(true); + const { data, error, isLoading } = useSWR("/api/score/week", fetcher); - useEffect(() => { - const fetchData = () => { - setIsLoading(true); - return fetch("/api/score/week") - .then((response) => { - if (!response.ok) { - throw new Error("Failed to fetch data"); - } - return response.json(); - }) - .then((result) => setData(result)) - .catch((error) => console.error("Error fetching data:", error)) - .finally(() => setIsLoading(false)); - }; - - fetchData(); - }, []); + if (error) { + console.error("Failed to fetch data"); + } const getEmoji = (rank: number) => { switch (rank) { diff --git a/app/src/functions/fetcher.ts b/app/src/functions/fetcher.ts new file mode 100644 index 0000000..7d607f7 --- /dev/null +++ b/app/src/functions/fetcher.ts @@ -0,0 +1,2 @@ +export const fetcher = (...args: [RequestInfo, RequestInit?]) => + fetch(...args).then((res) => res.json());