From 318ddfba573b27048f831e2bd693f8170952d482 Mon Sep 17 00:00:00 2001 From: WCY-dt <834421194@qq.com> Date: Mon, 29 Apr 2024 22:14:13 +0800 Subject: [PATCH] Refactor data fetching and loading logic --- src/components/clusters.tsx | 12 ++++++++++- src/components/content.tsx | 2 +- src/routers/router.tsx | 25 +++++++++++++++------- src/services/collectionFetcher.ts | 24 +++++++++++++++++++++ src/services/dataFetcher.ts | 35 ++++++++++++++++--------------- src/styles/loading.css | 24 +++++++++++++++++++++ 6 files changed, 96 insertions(+), 26 deletions(-) create mode 100644 src/services/collectionFetcher.ts create mode 100644 src/styles/loading.css diff --git a/src/components/clusters.tsx b/src/components/clusters.tsx index 9a91d23..202c146 100644 --- a/src/components/clusters.tsx +++ b/src/components/clusters.tsx @@ -3,6 +3,7 @@ import LinkCard from '../components/linkCard'; import ClearFilter from '../utils/clearFilter'; import { fetchAndFilterData } from '../services/dataFetcher'; import '../styles/clusters.css'; +import '../styles/loading.css'; interface ClustersProps { dataKey: string; @@ -13,11 +14,20 @@ interface ClustersProps { function Clusters({ dataKey, searchTerm, setSearchTerm }: ClustersProps) { const [clusters, setClusters] = useState([]); const [selectedCategory, setSelectedCategory] = useState(null); + const [isLoading, setIsLoading] = useState(true); useEffect(() => { - fetchAndFilterData(dataKey, true, selectedCategory, searchTerm, setClusters); + setIsLoading(true); + fetchAndFilterData(dataKey, true, selectedCategory, searchTerm, setClusters) + .finally(() => setIsLoading(false)); }, [dataKey, selectedCategory, searchTerm]); + if (isLoading) { + return ( +
+ ); + } + return ( <>

{dataKey}

diff --git a/src/components/content.tsx b/src/components/content.tsx index 17c62fe..948b901 100644 --- a/src/components/content.tsx +++ b/src/components/content.tsx @@ -14,7 +14,7 @@ function Content({ routes, searchTerm, setSearchTerm }: ContentProps) {
} + element={} /> {Object.entries(routes).map(([path, element]) => ( (true); + + const [routes, setRoutes] = useState({}); + useEffect(() => { + setIsLoading(true); + fetchCollection(setRoutes) + .finally(() => setIsLoading(false)); + }, []); + + if (isLoading) { + return ( +
+ ); + } return ( diff --git a/src/services/collectionFetcher.ts b/src/services/collectionFetcher.ts new file mode 100644 index 0000000..e3037d2 --- /dev/null +++ b/src/services/collectionFetcher.ts @@ -0,0 +1,24 @@ +export function fetchCollection(setRoutes: (value: {}) => void) { + return new Promise(async (resolve, reject) => { + const api = "https://api.mind.ch3nyang.top"; + let url = `${api}/collection`; + + try { + const response = await fetch(url, { method: 'GET' }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data: string[] = await response.json(); + let routes: { [key: string]: string } = {}; + data.forEach((collection) => { + routes[`/${collection.toLowerCase()}`] = collection; + }); + setRoutes(routes); + resolve(undefined); + } catch (e) { + console.error(`Fetch failed: ${(e as Error).message}`); + console.error(`Failed URL: ${url}`); + reject(e); + } + }); +} \ No newline at end of file diff --git a/src/services/dataFetcher.ts b/src/services/dataFetcher.ts index 257c11b..3a448b5 100644 --- a/src/services/dataFetcher.ts +++ b/src/services/dataFetcher.ts @@ -5,30 +5,31 @@ export function fetchAndFilterData( searchTerm: string = '', setClusters: (value: ClusterProps[]) => void ) { - const api = "https://api.mind.ch3nyang.top"; - let url = `${api}/card?collection=${dataKey}`; - if (selectedCategory) { - url += `&category=${selectedCategory}`; - } - if (searchTerm) { - url += `&search=${searchTerm}`; - } + return new Promise(async (resolve, reject) => { + const api = "https://api.mind.ch3nyang.top"; + let url = `${api}/card?collection=${dataKey}`; + if (selectedCategory) { + url += `&category=${selectedCategory}`; + } + if (searchTerm) { + url += `&search=${searchTerm}`; + } - fetch(url, { method: 'GET' }) - .then(response => { + try { + const response = await fetch(url, { method: 'GET' }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } - return response.json(); - }) - .then(data => { + let data = await response.json(); if (isRandom) { data = data.sort(() => Math.random() - 0.5); } setClusters(data); - }) - .catch(e => { - console.error(`Fetch failed: ${e.message}`); + resolve(undefined); + } catch (e) { + console.error(`Fetch failed: ${(e as Error).message}`); console.error(`Failed URL: ${url}`); - }); + reject(e); + } + }); } \ No newline at end of file diff --git a/src/styles/loading.css b/src/styles/loading.css new file mode 100644 index 0000000..7710c04 --- /dev/null +++ b/src/styles/loading.css @@ -0,0 +1,24 @@ +.loading { + border: 16px solid #f3f3f3; + border-radius: 50%; + border-top: 16px solid black; + width: 120px; + height: 120px; + animation: spin 2s linear infinite; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} \ No newline at end of file