useNoRecursiveRenders
can cause all of its children to be unmounted from the DOM
#39044
Labels
[Focus] Accessibility (a11y)
Changes that impact accessibility and need corresponding review (e.g. markup changes).
[Package] Block editor
/packages/block-editor
[Type] Bug
An existing feature does not function as intended
Description
Discovered when debugging #38169.
As the title says, the
RecursionProvider
returned byuseNoRecursiveRenders
can cause all of its children to unmount and remount from the DOM, which can lead to issues like focus loss, and may also be bad for performance.The explanation for this is a little lengthy, so buckle in.
The first important thing to know if that when using function components, React uses the function reference during render to reconcile the DOM. If that function reference changes, React considers it to be a completely different component, so when rendering it unmounts it and remounts what it considers the new component. It makes sense because the function reference is the only way React knows that a component is the same one across two renders.
Looking at the code for
useNoRecursiveRenders
, we can see that it usesuseCallback
to define a React component:gutenberg/packages/block-editor/src/components/use-no-recursive-renders/index.js
Lines 64 to 71 in c7d1558
When
newRenderedBlocks
changes, the function reference for theProvider
also changes, which is the root cause of the issue. In the navigation block, this happens when selecting a new menu—almost the entire block will be unmounted and remounted.Tracing back a little, the unique id for the currently selected menu is passed to
useNoRecursiveRenders
which results innewRenderedBlocks
being recalculated:gutenberg/packages/block-editor/src/components/use-no-recursive-renders/index.js
Lines 60 to 63 in c7d1558
Provider
.Step-by-step reproduction instructions
The easiest way to test this is in the Navigation Block.
The only thing to be aware of is that there are multiple causes of this bug in the Navigation Block, not just the recursion provider.
Screenshots, screen recording, code snippet
No response
Environment info
No response
Please confirm that you have searched existing issues in the repo.
Yes
Please confirm that you have tested with all plugins deactivated except Gutenberg.
Yes
The text was updated successfully, but these errors were encountered: