Avoid rerending the current block if the previous block change#12379
Conversation
packages/blocks/src/api/utils.js
Outdated
There was a problem hiding this comment.
Since we're using strings now for RichText values, the isEqual is useless I think.
There was a problem hiding this comment.
=== will check that the values are of the same type and that their values match, so it'll work nicely in the context of two strings, yes.
There was a problem hiding this comment.
Since we're using strings now for RichText values, the
isEqualis useless I think.
I also don't think it's something we should have ever wanted, even for non-primitive types, since even if the values are deeply equal, the test seems like it should be more concerned about whether the value has ever changed from its default-assigned reference.
There was a problem hiding this comment.
the value has ever changed from its default-assigned reference.
The reason was: you type in a paragraph, you backspace, you click outside of the block. You have an empty paragraph but a new reference.
There was a problem hiding this comment.
And to me I'd be fine to call that "modified" 🤷♂️
There was a problem hiding this comment.
As discussed here #11899 (comment) this means we now show the inserter even if the previous block is empty.
There was a problem hiding this comment.
Nice removal! Should be an excellent improvement not to load two blocks every single time.
There was a problem hiding this comment.
Internal filter not useful anymore because we got rid of "layout" attributes.
sgomes
left a comment
There was a problem hiding this comment.
The code changes look good to me. Great work, @youknowriad! This is an excellent example of where a small UX compromise can lead to a big performance boost.
I'll try to replicate your results in the meantime, but code-wise looks good to merge 👍
|
I see a similar improvement (23%) in my machine 👍 |
849c449 to
c3987ff
Compare
aduth
left a comment
There was a problem hiding this comment.
I like this in an effort of reducing the unpredictability around when and where a sibling inserter is shown. One thing I might worry about is: Before we'd never shown a sibling inserter around an empty default block at all, and now we show it after but not before an empty default block. It seems to me we'd probably be better off one way or the other. In other words, do we even need this canShowInBetweenInserter at all ?
packages/blocks/src/api/utils.js
Outdated
There was a problem hiding this comment.
Since we're using strings now for RichText values, the
isEqualis useless I think.
I also don't think it's something we should have ever wanted, even for non-primitive types, since even if the values are deeply equal, the test seems like it should be more concerned about whether the value has ever changed from its default-assigned reference.
| const { clientId, previousBlockClientId, nextBlockClientId, onMerge } = this.props; | ||
|
|
||
| const { clientId, getPreviousBlockClientId, getNextBlockClientId, onMerge } = this.props; | ||
| const previousBlockClientId = getPreviousBlockClientId( clientId ); |
There was a problem hiding this comment.
Another thing which will be nice to move to the dispatch handler when #11851 lands. Or, at least, our non-conventional use of selectors as functions directly within the component is concerning (but largely in its being unconventional).
There was a problem hiding this comment.
Or, at least, our non-conventional use of selectors as functions directly within the component is concerning (but largely in its being unconventional).
On further reflection, I think I could articulate my concern better in being a diminished distinction between withSelect as serving to provide data and withDispatch as serving to provide behavior, where what we've done here is more in the realm of a behavior.
To clarify, not something which needs to be addressed here.
| isSelected, | ||
| isParentOfSelectedBlock, | ||
|
|
||
| // We only care about this value when the shift key is pressed. |
There was a problem hiding this comment.
This comment is no longer strictly applicable to the use-case, since there's now a second use-case.
|
|
||
| return every( attributeKeys, ( key ) => | ||
| isEqual( newDefaultBlock.attributes[ key ], block.attributes[ key ] ) | ||
| return every( blockType.attributes, ( value, key ) => |
There was a problem hiding this comment.
There's a subtlety here in how we use the block type's attributes definition instead of the actual default block we've created; I assume that's so we account for keys which don't have a default assigned and thus would be absent from the default block, but potentially present in the block being tested?
Some comment to this effect could help clarify for future maintainers.
There was a problem hiding this comment.
My thinking is that the previous implementation was needed because undeclared attributes were persisted initially, but that's not the case anymore.
| @@ -40,14 +39,10 @@ export function isUnmodifiedDefaultBlock( block ) { | |||
| } | |||
|
|
|||
| const newDefaultBlock = createBlock( defaultBlockName ); | |||
There was a problem hiding this comment.
Maybe a red herring, but createBlock seems like something which in its current state is somewhat non-trivial, at least if we expect it to be called frequently. Do we need to create a new instance of the block each time this function is called?
There was a problem hiding this comment.
We need the "normalized" attributes (default values), An alternative would be to avoid this behavior "isUnmodified" if the default block has been changed. And just rely on very quick but static checks as we know the block is "paragraph".
I don't know, I'll explore it separately :) |
|
or actually, I'll update this PR iff it seems useless. |
My worry is that the pull request in its current form is the worst of all options, between:
|
|
I pushed a commit to always show the in-between inserter. |
FYI @jasmussen |
|
The insertion point line is not shown when hovering a block option in the inserter before an empty block. Am I correct in assuming that this would be resolved by #12384 ? |
|
I think that's correct @aduth now that you mention that, I think I know why we don't show the inserter and the insertion point for empty blocks, that's because we replace them instead of adding new blocks when you choose a block from the inserter. I personally think it's a fine "compromise" for performance to show them even if we replace the block instead of inserting new ones. |
I find that a bit peculiar as well 😆 But it's neither here nor there, as I don't really find this to really have an effect (negative or positive) on the expectation of that behavior. |
|
Nice to see this improvement! |
* Avoid rerending the current block if the previous block change * Always show the sibling inserter * Optimize the insertion point component (#12384)
* Avoid getBlock in block-list/block * Update data docs * Fix unit tests post rebase :) * Rename props * Clarify the filter position * Avoid repeating the selector dependants * Fix small typo in the docs * Avoid rerending the current block if the previous block change (#12379) * Avoid rerending the current block if the previous block change * Always show the sibling inserter * Optimize the insertion point component (#12384) * Fix lock file * Fix linting

This PR builds on top of #11899 And it's another refactoring to the
BlockListBlockcomponent to avoid useless selectors.In my testing. Key press events are
22%faster in long posts.