-
Notifications
You must be signed in to change notification settings - Fork 6
Fix preview width when searching or filtering patterns #115
Conversation
// Helps ensure PatternPreview iFrames are the right size. | ||
useWindowResize(); | ||
useForceRerend( [ themePatterns ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main problem relates to not being certain we are getting the correct BoundingClientRect
(and thus scale
) in PatternPreview
, even when new categories are filtered.
This was the simplest way I could think of to be absolutely sure all previews in the grid are freshly rendered with the correct BoundingClientRect
while using a derived state for previewContainerSize
.
The patterns passed via themePatterns
are filtered by search term or selected category, so we can use it instead of passing any new props.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good way to force rerendering when the filtered patterns change.
export default function useForceRerend< T extends unknown >( | ||
dependencies: T[] = [] | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is okay to allow pretty much any type of value in the dependencies
array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, useForceRerend()
is agnostic to the component that calls it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactoring my solution from yesterday here 🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, it's always good to look back and improve things
// Do not cause a re-render on first render. | ||
if ( initialRender.current ) { | ||
initialRender.current = false; | ||
} else { | ||
setForceUpdate( dependencies ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setForceUpdate()
should only run when dependencies
are updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you see a performance boost compared to not using the if
guard clause?
diff --git a/wp-modules/app/js/src/hooks/useForceRerend.ts b/wp-modules/app/js/src/hooks/useForceRerend.ts
index b8655ffc..59db5d80 100644
--- a/wp-modules/app/js/src/hooks/useForceRerend.ts
+++ b/wp-modules/app/js/src/hooks/useForceRerend.ts
@@ -11,21 +11,12 @@ export default function useForceRerend< T extends unknown >(
dependencies: T[] = []
) {
const [ , setForceUpdate ] = useState< T[] | WindowDimensions >();
- const initialRender = useRef( true );
useLayoutEffect( () => {
- // Do not cause a re-render on first render.
- if ( initialRender.current ) {
- initialRender.current = false;
- } else {
- setForceUpdate( dependencies );
- }
+ setForceUpdate( dependencies );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd vote to keep this if/else
only if it adds a big performance boost.
Otherwise, simply calling setForceUpdate( dependencies );
might be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In testing, it does not really improve performance in any meaningful way (especially considering that we are potentially get just one additional state update on initial render — it's a non-issue right now).
That block and ref were removed in 0884c93!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, 0884c93 looks really good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @mike-day,
Nice work! A few implementation comments below, but this is a nice improvement.
Looks like my comments didn't show up in the review. Adding some now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are the comments I meant to leave before
// Helps ensure PatternPreview iFrames are the right size. | ||
useWindowResize(); | ||
useForceRerend( [ themePatterns ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good way to force rerendering when the filtered patterns change.
// Do not cause a re-render on first render. | ||
if ( initialRender.current ) { | ||
initialRender.current = false; | ||
} else { | ||
setForceUpdate( dependencies ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd vote to keep this if/else
only if it adds a big performance boost.
Otherwise, simply calling setForceUpdate( dependencies );
might be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, it's always good to look back and improve things
/** | ||
* Re-render the calling component when the window is resized. | ||
* | ||
* Optionally include an array of dependencies to trigger a re-render. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Optionally include an array of dependencies to trigger a re-render. | |
* Include an array of dependencies to trigger a re-render. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last nitpick 🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just noticed that and fixed right before I saw this 😆
Covered with 0c1d8d9 — I went with: Re-render the calling component when the window is resized or dependencies update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, you beat me to it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great 1-liner!
…into try/force-rerender-all-stale-previews
Related to the work in #109 and #95 — preview widths are sometimes stale when filtering by clicking category options or searching in the patterns view:
The width expands when it is the only filtered option, but remains at full-width when it should be resized to accommodate a second result.
This PR expands on and replaces the
useWindowSize
hook in #109 to allow other dependencies (such asfilteredPatterns
/themePatterns
) to also trigger a re-render:Now, regardless of how the user searches, clicks through categories, or resizes the window, we can also be sure a fresh grid of pattern previews with correct dimensions is displayed.
How to test
Notes
Not that this was expected to change, but even with the extra rendering introduced by these changes, Lighthouse scores remain screaming fast. Care was taken to ensure this does not cause an unneeded re-render on initial load: