Skip to content
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

Inserter: Prevent unnecessary re-renders when selecting a different block #7724

Closed
wants to merge 2 commits into from

Conversation

gziolo
Copy link
Member

@gziolo gziolo commented Jul 5, 2018

Description

When testing one of the performance improvements I noticed that Inserter component re-renders each time something changes in the editor. This is very unexpected because it is just a button.

The improvement I propose is to move all store operations to the child component which is the one that needs those data to be fetched. The only check that is left is whether there is any block registered to make sure we don't display the inserter when there no blocks available.

It still needs to be verified how it interacts with the template lock.

How has this been tested?

Manually with Highlight Updates enabled in React devTools.

Screenshots

Before

inserter-blink-when-using-keyboard

After

inserter-blink-when-using-keyboard-after

Types of changes

Performance optimization.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.

@gziolo gziolo added [Feature] Inserter The main way to insert blocks using the + button in the editing interface [Type] Performance Related to performance efforts labels Jul 5, 2018
@gziolo gziolo self-assigned this Jul 5, 2018
@gziolo gziolo requested review from aduth, jorgefilipecosta and a team July 5, 2018 13:15
@jorgefilipecosta
Copy link
Member

jorgefilipecosta commented Jul 5, 2018

This approach is similar to what we tried in #6796. The approach was discarded because we made a call to isUnmodifiedDefaultBlock on every state change so we were not sure if that approach was better on not because isUnmodifiedDefaultBlock is a complex function. I think this PR does not contain this problem.

@gziolo
Copy link
Member Author

gziolo commented Jul 5, 2018

@jorgefilipecosta - I think it is different, because I moved all this logic to the child component which isn't displayed by default. The only issue with this approach is that it might happen that we display the inserter when there are no blocks to insert and it will show no blocks message because of this relaxed check: https://github.com/WordPress/gutenberg/pull/7724/files#diff-922ca3021f1da894e7d2fe1e9e533335R38.

Copy link
Member

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes a bunch of sense to me; we shouldn't have components whose job it is to pass state info to their child components instead of having the children use redux.

I can't speak to locking but otherwise looks good to me. Tested locally and saw similar results in Firefox with fewer re-draws.

onClose();
};

return <InserterMenu items={ items } onSelect={ onSelect } rootUID={ rootUID } />;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice to see removed; it's always a bit of a code smell to have a component that just passes props down to other components without using them.

const { index, rootUID, layout } = insertionPoint;
const { name, initialAttributes } = item;
const insertedBlock = createBlock( name, { ...initialAttributes, layout } );
if ( selectedBlock && isUnmodifiedDefaultBlock( selectedBlock ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function is a bit mushed together and could use some whitespace/breathing room around conditionals, so I've pushed a little style tweak.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks 👍

Copy link
Member

@jorgefilipecosta jorgefilipecosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we select the column block and then we try to insert inside the other column, we see the no available blocks message.
screen shot 2018-07-06 at 10 37 39

Before the insert button did not appear in this case which was also not correct. This points to a problem in our inserter where it always references the currently selected block as the inserter position. While we sometimes put the button in places where it should use a specific position different from the currently selected one. This also causes a bug where inline images may be inserted in the wrong place (but it is already present in master).

I think this seems to work great.
We are now showing the inserter all the times, even in cases where we can not obviously insert (e.g: general CPT template Lock). So we have a UX decision here cc: @karmatosed. Should we show the inserter all the time, even if no blocks are available to increase the performance? Or should we hide the inserter if we already know that the user will not be able to insert blocks?
I don't have a strong option on the best option here.

To note that I found a bug where our hiding logic of the button does not account inline blocks so if locking exists we can not insert inline images in paragraphs because we hide the inserter, this PR shows the inserter all the time so the problem gets fixed.
Technically going with this option of showing the inserter all the time is much simpler as I feel the logic will only get complex with layout blocks and other mechanisms.

I will create issues for the existing problems I noticed while testing this.

@gziolo
Copy link
Member Author

gziolo commented Jul 6, 2018

We are now showing the inserter all the times, even in cases where we can not obviously insert (e.g: general CPT template Lock). So we have a UX decision here cc: @karmatosed. Should we show the inserter all the time, even if no blocks are available to increase the performance? Or should we hide the inserter if we already know that the user will not be able to insert blocks?

I was afraid, it might happen with all the complex logic we have for child blocks and similar concepts. Assuming we don't want to show the button when there are no blocks to pick, should we gray it out instead to keep it as part of the UI but inform the user that it isn't usable?

@jorgefilipecosta
Copy link
Member

I was afraid, it might happen with all the complex logic we have for child blocks and similar concepts. Assuming we don't want to show the button when there are no blocks to pick, should we gray it out instead to keep it as part of the UI but inform the user that it isn't usable?

I guess it depends on the situation. On the global inserter, we should probably show it in gray (I mean a different gray). On the inline buttons that appear they should probably not appear if it is not possible to insert.

@gziolo gziolo added the Needs Design Feedback Needs general design feedback. label Jul 10, 2018
@karmatosed
Copy link
Member

Assuming we don't want to show the button when there are no blocks to pick, should we gray it out instead to keep it as part of the UI but inform the user that it isn't usable?

Greying out is the right approach here. Where possible not seeing at all is the best but if that can't happen then lets go for background state.

@karmatosed karmatosed removed the Needs Design Feedback Needs general design feedback. label Jul 11, 2018
@aduth
Copy link
Member

aduth commented Sep 13, 2018

Is it likely this will be resumed, or can it be closed?

@aduth aduth added the [Status] Stale Gives the original author opportunity to update before closing. Can be reopened as needed. label Sep 13, 2018
@gziolo
Copy link
Member Author

gziolo commented Sep 28, 2018

I would like to do another round of refactoring and improve the logic which decides whether the button should be rendered.

@gziolo
Copy link
Member Author

gziolo commented Oct 30, 2018

@aduth opened a more up to date version of the same change and it's also more close to the actual implementation. Closing this one in favor of #11243.

@gziolo gziolo closed this Oct 30, 2018
@gziolo gziolo deleted the update/prevent-obsolete-inserter-rerenders branch October 30, 2018 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Inserter The main way to insert blocks using the + button in the editing interface [Status] Stale Gives the original author opportunity to update before closing. Can be reopened as needed. [Type] Performance Related to performance efforts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants