useToolsPanel: calculate menuItems in layout effect to avoid painting intermediate state #65494
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.
Fixes a visual glitch when displaying a tools panel in style editor. Go to global styles editor for individual blocks and in the list of blocks, click on Paragraph. At first, toolbar items with no content will appear:
only after a moment the full UI is rendered:
The cause of this is how the state of the panel is updated, calculating derived state in a cascade of effects:
This needs several rerenders and paints until the final state is achieved.
In our case, the state involved is the
menuItems
object and theisShown
value derived from it.This PR fixes that by using layout effect, so that all the updates happen without an intermediate paint that reveals the non-final UI state. See also #56536 which applied exactly the same fix at another place.
Only the first commit is needed to actually fix the glitch. The rest is using
useLayoutEffect
also for other state-updating effects in the same file. And removing some unneeded dependencies fromuseCallback
anduseEffect
calls, namely state setters.The next step could be a bigger refactoring to make the state updates more streamlined. We don't need effects: they only trigger rerenders. We could use
useMemo
or, for state updates that need to see the previous state, auseReducer
.