tangled
alpha
login
or
join now
nekomimi.pet
/
bunsite
0
fork
atom
personal website
0
fork
atom
overview
issues
pulls
pipelines
lazy load vibes in batches instead of all at once
nekomimi.pet
3 weeks ago
375c495f
0b0d8233
1/1
deploy.yml
success
41s
+31
-7
1 changed file
expand all
collapse all
unified
split
src
components
sections
Vibes.tsx
+31
-7
src/components/sections/Vibes.tsx
···
1
1
-
import { useEffect, useState } from "react"
1
1
+
import { useEffect, useRef, useState } from "react"
2
2
+
3
3
+
const BATCH_SIZE = 20
2
4
3
5
export function Vibes() {
4
4
-
const [vibes, setVibes] = useState<string[]>([])
6
6
+
const [allVibes, setAllVibes] = useState<string[]>([])
7
7
+
const [visibleCount, setVisibleCount] = useState(BATCH_SIZE)
8
8
+
const sentinelRef = useRef<HTMLDivElement>(null)
5
9
6
10
useEffect(() => {
7
11
fetch("/vibes/manifest.json")
8
12
.then((res) => res.json())
9
9
-
.then(setVibes)
10
10
-
.catch(() => setVibes([]))
13
13
+
.then(setAllVibes)
14
14
+
.catch(() => setAllVibes([]))
11
15
}, [])
12
16
17
17
+
useEffect(() => {
18
18
+
const sentinel = sentinelRef.current
19
19
+
if (!sentinel) return
20
20
+
21
21
+
const observer = new IntersectionObserver(
22
22
+
(entries) => {
23
23
+
if (entries[0].isIntersecting) {
24
24
+
setVisibleCount((c) => Math.min(c + BATCH_SIZE, allVibes.length))
25
25
+
}
26
26
+
},
27
27
+
{ rootMargin: "400px" }
28
28
+
)
29
29
+
30
30
+
observer.observe(sentinel)
31
31
+
return () => observer.disconnect()
32
32
+
}, [allVibes.length])
33
33
+
34
34
+
const visible = allVibes.slice(0, visibleCount)
35
35
+
13
36
return (
14
37
<div className="vibes-container">
15
15
-
{vibes.map((vibe, index) => {
38
38
+
{visible.map((vibe, index) => {
16
39
const isVideo = vibe.endsWith(".mp4") || vibe.endsWith(".mov") || vibe.endsWith(".webm")
17
40
return isVideo ? (
18
18
-
<video key={index} src={vibe} className="vibe-item" controls loop muted />
41
41
+
<video key={vibe} src={vibe} className="vibe-item" controls loop muted preload="none" />
19
42
) : (
20
20
-
<img key={index} src={vibe} alt="" className="vibe-item" loading="lazy" />
43
43
+
<img key={vibe} src={vibe} alt="" className="vibe-item" loading="lazy" decoding="async" />
21
44
)
22
45
})}
46
46
+
{visibleCount < allVibes.length && <div ref={sentinelRef} style={{ height: 1 }} />}
23
47
</div>
24
48
)
25
49
}