Skip to content

Commit da3163e

Browse files
committed
dog
1 parent 3453b01 commit da3163e

2 files changed

Lines changed: 97 additions & 0 deletions

File tree

src/pages/dog.astro

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
import Layout from "@/layouts/Layout.astro";
3+
import Dog from "@/tools/dog.tsx";
4+
---
5+
6+
<Layout title="dog">
7+
<Dog client:only="react" />
8+
</Layout>

src/tools/dog.tsx

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { useState, useEffect, useRef } from "react";
2+
3+
const MAX_CACHE_SIZE = 200;
4+
5+
interface DogApiResponse {
6+
message: string;
7+
status: string;
8+
}
9+
10+
export default function Dog() {
11+
const [currentImage, setCurrentImage] = useState<string>("");
12+
const [isLoading, setIsLoading] = useState(true);
13+
const cacheRef = useRef<string[]>([]);
14+
const isCachingCompleteRef = useRef(false);
15+
16+
const fetchNewDogImage = async () => {
17+
try {
18+
const response = await fetch("https://dog.ceo/api/breeds/image/random");
19+
const data: DogApiResponse = await response.json();
20+
21+
if (data.status === "success" && data.message) {
22+
const imageUrl = data.message;
23+
24+
// Preload the image
25+
const img = new Image();
26+
img.onload = () => {
27+
setCurrentImage(imageUrl);
28+
setIsLoading(false);
29+
30+
// Add to cache if not already there and cache not full
31+
if (!isCachingCompleteRef.current && !cacheRef.current.includes(imageUrl)) {
32+
cacheRef.current.push(imageUrl);
33+
34+
// Check if cache is now full
35+
if (cacheRef.current.length >= MAX_CACHE_SIZE) {
36+
isCachingCompleteRef.current = true;
37+
console.log(`Cache complete! ${MAX_CACHE_SIZE} dog pictures cached.`);
38+
}
39+
}
40+
};
41+
img.src = imageUrl;
42+
}
43+
} catch (error) {
44+
console.error("Error fetching dog image:", error);
45+
}
46+
};
47+
48+
const getRandomCachedImage = () => {
49+
if (cacheRef.current.length === 0) return;
50+
51+
const randomIndex = Math.floor(Math.random() * cacheRef.current.length);
52+
const imageUrl = cacheRef.current[randomIndex];
53+
54+
setCurrentImage(imageUrl);
55+
setIsLoading(false);
56+
};
57+
58+
useEffect(() => {
59+
// Initial fetch
60+
if (!isCachingCompleteRef.current) {
61+
fetchNewDogImage();
62+
} else {
63+
getRandomCachedImage();
64+
}
65+
66+
// Set up interval to fetch/cycle every second
67+
const interval = setInterval(() => {
68+
if (isCachingCompleteRef.current) {
69+
getRandomCachedImage();
70+
} else {
71+
fetchNewDogImage();
72+
}
73+
}, 1000);
74+
75+
return () => clearInterval(interval);
76+
}, []);
77+
78+
return (
79+
<div className="flex items-center justify-center min-h-screen p-4">
80+
{currentImage && (
81+
<img
82+
src={currentImage}
83+
alt="Random dog"
84+
className="max-w-full max-h-screen object-contain"
85+
/>
86+
)}
87+
</div>
88+
);
89+
}

0 commit comments

Comments
 (0)