Repository navigation
perf(gallery): memoise the gallery's derived values - #1307
Merged
nanaf6203-bit merged 1 commit intoOct 21, 2026
Merged
nanaf6203-bit merged 1 commit into
nanaf6203-bit merged 1 commit into
Conversation
The property detail view re-renders for plenty of reasons that have nothing to do with the photos - the currency toggle, a parent state change, an analytics update - and each of those re-renders rebuilt the thumbnail strip from scratch: a fresh slice(1, 5) array and four new next/image elements, even when the image list had not changed. - ImageGallery is wrapped in React.memo, so React skips the gallery outright when images and propertyName are unchanged. - Each thumbnail is a memoized component of its own, so a thumbnail whose props did not change is not re-rendered. - The image list, the thumbnail slice and the overflow counter are computed with useMemo, keyed on the image list. - The lightbox handlers are useCallbacks, so the lightbox keeps the same handler identity across renders. The rendered output is unchanged: the same images, the same thumbnails, the same overflow counter, the same empty state. A missing images prop is still handled - the list is normalised before anything reads it. Closes MettaChain#1266
|
@peaceshallom37-rgb Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
nanaf6203-bit
approved these changes
Oct 21, 2026
nanaf6203-bit
left a comment
Contributor
There was a problem hiding this comment.
Simple and effective — memoising those derived values should help. LGTM.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
ImageGallerysits inside the property detail view, which re-renders for plenty of reasons that have nothing to do with the photos — the currency toggle, a parent state change, an analytics update. Every one of those re-renders rebuilt the thumbnail strip: a freshslice(1, 5)array and four newnext/imageelements, even when the image list had not changed a byte.This memoizes the gallery so that those re-renders do not walk the photo tree.
The changes
ImageGalleryis wrapped inReact.memo. React skips the whole gallery whenimagesandpropertyNameare unchanged, so the images are not re-created at all.GalleryThumbnail, also memoized). A thumbnail depends on its image, its alt text and the open handler, so a re-render that leaves a thumbnail's props alone does not re-render it.useMemo, keyed on the image list.useCallbacks, so the lightbox keeps the same handler identity across renders.The rendered output is unchanged: the same images, the same thumbnails, the same overflow counter, the same empty state.
The image list is normalised before anything reads it, so a missing
imagesprop still renders the empty state instead of throwing.Tests
src/components/property/__tests__/ImageGallery.test.tsxcovers the behaviour that is easy to break:next/imagemock counts its renders);Notes for the reviewer
Another open PR (#1306) adds the i18n and the validation to the same file. The changes here are in different parts of it, but a merge conflict is likely and will have to be resolved by hand.
React.memocompares the props shallowly, so the caller has to pass the same array reference to get the benefit.PropertyDetailServerpassesproperty.images, which is stable, so it does. A freshly built array (property.images.filter(...)in the render body) would be a new reference on every render and would re-render the gallery as before. This is written up indocs/image-gallery.md.CI
The workflow run of this pull request is waiting for approval (
action_required), because it comes from a fork. It has to be approved before it starts.mainis currently red for reasons that are not related to this branch:npm run lintreports 82 errors andnpm run typecheckreports 472 errors across the repository (missingreact-pdfand@types/leaflettypings, for instance), and a set of wallet test suites fail. The same failures are onmainand on the other open branches. This branch adds no new lint, type or test failures —eslintandtscare clean on the files it touches, and the full jest run has the same 17 failing suites asmain(all of them pre-existing) with 4 more passing tests.Closes #1266