-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useAvailableAlignments: avoid useSelect subscription when alignments array is empty #55449
Conversation
Size Change: +8 B (0%) Total Size: 1.66 MB
ℹ️ View Unchanged
|
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.
Thank you, @jsnajdr!
The code looks good, and I couldn't spot regression in the alignment feature, and it should have a good e2e coverage (I think)
// If `isNoneOnly` is true, we'll be returning early because there is | ||
// nothing to filter on an empty array. We won't need the info from | ||
// the `useSelect` but we must call it anyway because Rules of Hooks. | ||
// So the callback returns early to avoid block editor subscription. | ||
if ( isNoneOnly ) { | ||
return [ false, false, false ]; | ||
} |
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.
Hopefully, the comment will mitigate this odd return value 😄
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.
Yes, it bothers me that it looks so weird 🙂
On the other hand, this patch demonstrates a useSelect
usage pattern that I think its quite neat and we could adopt it more widely: returning arrays instead of objects!
When writing:
const { themeSupportsLayout } = useSelect( ( select ) => ( { themeSupportsLayout: ... } ) );
the themeSupportsLayout
identifier is repeated twice, and constructing and destructuring the object is a bit unwieldy. Compare this to an array:
const [ themeSupportsLayout ] = useSelect( ( select ) => ( [ ... ] ) );
That's much shorter and yet you don't lose any information. We're replacing the themeSupportsLayout
with a 0
array index, basically. The field name doesn't matter because it's immediately destructured anyway.
Three optimizations related to the
useAvailableAlignments
hook and thealign
attribute.There's an observation that if the
controls
array passed touseAvailableAlignments( controls )
is an[]
empty array or[ 'none' ]
, the return value of the hook is going to be[]
. The hook filters thecontrols
array depending on what the theme and the parent layout says, but there's not much to do with an empty array.Therefore, in this case, we can make the
useSelect
insideuseAvailableAlignments
into a noop, so that it doesn't select fromcore/block-editor
store at all and doesn't create a subscription.The second observation is that sometimes we call
useAvailableAlignments
twice. ThewithToolbarControls
HOC calls it the first time, and then theBlockAlignmentControl
component calls it the second time, on the result of the first call. We can remove thewithToolbarControls
call. It checks only for an empty array anyway, and theBlockAlignmentControl
will do the same check once again.The third optimization is in the
withDataAlign
HOC. If thealign
attribute isundefined
, which it almost always is, the HOC does nothing at all. All the hook calls can be extracted into the helperBlockListBlockWithDataAlign
component that is rendered only whenalign
is defined.On a large post with 1400 blocks I was able to reduce the
core/block-editor
subscriptions by 2900, i.e., 2 per block.This improvement is a part of the program outlined in #54819.