perf: wrap BookCard and BookImage with React.memo

Prevent unnecessary re-renders of book grid items when parent
components update without changing book data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-21 13:03:24 +01:00
parent 6df743b2e6
commit 49621f3fb1

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useState } from "react"; import { memo, useState } from "react";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { BookDto, ReadingStatus } from "../../lib/api"; import { BookDto, ReadingStatus } from "../../lib/api";
@@ -17,7 +17,7 @@ interface BookCardProps {
readingStatus?: ReadingStatus; readingStatus?: ReadingStatus;
} }
function BookImage({ src, alt }: { src: string; alt: string }) { const BookImage = memo(function BookImage({ src, alt }: { src: string; alt: string }) {
const [isLoaded, setIsLoaded] = useState(false); const [isLoaded, setIsLoaded] = useState(false);
const [hasError, setHasError] = useState(false); const [hasError, setHasError] = useState(false);
@@ -54,9 +54,9 @@ function BookImage({ src, alt }: { src: string; alt: string }) {
/> />
</div> </div>
); );
} });
export function BookCard({ book, readingStatus }: BookCardProps) { export const BookCard = memo(function BookCard({ book, readingStatus }: BookCardProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const coverUrl = book.coverUrl || `/api/books/${book.id}/thumbnail`; const coverUrl = book.coverUrl || `/api/books/${book.id}/thumbnail`;
const status = readingStatus ?? book.reading_status; const status = readingStatus ?? book.reading_status;
@@ -128,7 +128,7 @@ export function BookCard({ book, readingStatus }: BookCardProps) {
</div> </div>
</Link> </Link>
); );
} });
interface BooksGridProps { interface BooksGridProps {
books: (BookDto & { coverUrl?: string })[]; books: (BookDto & { coverUrl?: string })[];