feat: improve hydration handling and add dependencies

- Add hydration state check to PhotoGallery component to prevent SSR/client mismatch
- Update bun.lock with Express and CORS dependencies for mock API
- Add placeholder image for better development experience
This commit is contained in:
xujiang
2025-07-08 17:39:12 +08:00
parent 4d85b6bd24
commit 55932ee587
3 changed files with 124 additions and 5 deletions

View File

@ -1,6 +1,6 @@
"use client"
import { useState } from "react"
import { useState, useEffect } from "react"
import Image from "next/image"
import { Card } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
@ -29,6 +29,11 @@ interface PhotoGalleryProps {
export function PhotoGallery({ photos, onPhotoClick }: PhotoGalleryProps) {
const [loadedImages, setLoadedImages] = useState<Set<number>>(new Set())
const [isHydrated, setIsHydrated] = useState(false)
useEffect(() => {
setIsHydrated(true)
}, [])
const handleImageLoad = (photoId: number) => {
setLoadedImages((prev) => new Set(prev).add(photoId))
@ -43,13 +48,13 @@ export function PhotoGallery({ photos, onPhotoClick }: PhotoGalleryProps) {
onClick={() => onPhotoClick(photo)}
>
<div className="relative aspect-[4/3] overflow-hidden">
{!loadedImages.has(photo.id) && <div className="absolute inset-0 bg-gray-100 animate-pulse" />}
{isHydrated && !loadedImages.has(photo.id) && <div className="absolute inset-0 bg-gray-100 animate-pulse" />}
<Image
src={photo.src || "/placeholder.svg"}
alt={photo.title}
fill
className={`object-cover transition-all duration-500 group-hover:scale-110 ${
loadedImages.has(photo.id) ? "opacity-100" : "opacity-0"
isHydrated && loadedImages.has(photo.id) ? "opacity-100" : !isHydrated ? "opacity-100" : "opacity-0"
}`}
onLoad={() => handleImageLoad(photo.id)}
/>