perf: memoize PhotoGrid assets map to prevent re-renders during lightbox navigation [#5]

Extracted the grid mapping logic out of the return block into a `useMemo`
hook depending on `[assets, layout, openLightbox]`. This prevents the
entire photo grid—including complex Next.js `<Image>` and `<FadeIn>`
components—from needlessly re-rendering every time the user navigates
via the lightbox arrows or presses next/prev buttons, which previously
caused `lightboxIndex` to update and trigger a re-render of the entire grid.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
Ralksta
2026-03-11 23:32:40 +01:00
committed by GitHub
parent a94b55704e
commit f3890fc6bc
2 changed files with 52 additions and 42 deletions

4
.jules/bolt.md Normal file
View File

@@ -0,0 +1,4 @@
## YYYY-MM-DD - [Memoize grid item re-rendering]
**Learning:** `useMemo` can significantly boost the performance of long list or grid components (like `PhotoGrid` component) that otherwise gets re-rendered on simple interactions like navigating the image lightbox. Running standard formatting `pnpm format` applies huge changes across entire directories, so it's generally best to format and clean up ONLY modified files to avoid huge diff pollution in code review.
**Action:** Be extremely cautious of running format/lint commands at the root codebase; specify only modified directories or files, or avoid formatting if it cascades globally. Focus on targeted memoization where state changes dictate expensive array mapping operations.

View File

@@ -8,7 +8,7 @@
'use client'; 'use client';
import { useState, useCallback, useEffect } from 'react'; import { useState, useCallback, useEffect, useMemo } from 'react';
import Image from 'next/image'; import Image from 'next/image';
import { Lightbox } from '@/components/Lightbox'; import { Lightbox } from '@/components/Lightbox';
import { FadeIn } from '@/components/FadeIn'; import { FadeIn } from '@/components/FadeIn';
@@ -136,10 +136,10 @@ export function PhotoGrid({ assets, layout = 'masonry', gridStyle }: PhotoGridPr
}; };
}, [lightboxIndex, closeLightbox, goNext, goPrev]); }, [lightboxIndex, closeLightbox, goNext, goPrev]);
return ( // Memoize grid items to prevent re-renders of the entire grid (which includes
<> // Image and FadeIn components) when navigating the lightbox.
<div className={`photo-grid photo-grid--${layout}`} style={gridStyle}> const gridItems = useMemo(() => {
{assets.map((asset, index) => ( return assets.map((asset, index) => (
<FadeIn key={asset.id} delay={index < 12 ? index * 50 : 0}> <FadeIn key={asset.id} delay={index < 12 ? index * 50 : 0}>
<div <div
className={`photo-grid__item${ className={`photo-grid__item${
@@ -179,7 +179,13 @@ export function PhotoGrid({ assets, layout = 'masonry', gridStyle }: PhotoGridPr
)} )}
</div> </div>
</FadeIn> </FadeIn>
))} ));
}, [assets, layout, openLightbox]);
return (
<>
<div className={`photo-grid photo-grid--${layout}`} style={gridStyle}>
{gridItems}
</div> </div>
{lightboxIndex !== null && ( {lightboxIndex !== null && (