-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Block editor: create useBlockRef and useBlockElement for better access #29573
Conversation
Size Change: +669 B (0%) Total Size: 1.39 MB
ℹ️ View Unchanged
|
packages/block-editor/src/components/block-list/block-popover.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/block-list/use-block-props/use-block-refs.js
Outdated
Show resolved
Hide resolved
b326f99
to
902c9c6
Compare
@@ -235,6 +222,9 @@ function BlockPopover( { | |||
__experimentalOnIndexChange={ ( index ) => { | |||
initialToolbarItemIndexRef.current = index; | |||
} } | |||
// Resets the index whenever the active block changes so | |||
// this is not persisted. See https://github.com/WordPress/gutenberg/pull/25760#issuecomment-717906169 | |||
key={ clientId } |
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.
Remounting the component is better because the block element may change immediately from one to the other. Previously the block node would be undefined between client ID changes.
@@ -100,8 +96,7 @@ function InsertionPointPopover( { | |||
'vertical'; | |||
|
|||
return { | |||
previousElement: getBlockDOMNode( previous, ownerDocument ), | |||
nextElement: getBlockDOMNode( next, ownerDocument ), | |||
previousClientId: previous, |
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.
Note that previously the element wouldn't update if it changed because it's memoized by client ID.
* | ||
* @return {Node|undefined} Preview container DOM node. | ||
*/ | ||
export function getBlockPreviewContainerDOMNode( clientId, doc ) { |
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.
This function is not used anywhere.
@@ -53,7 +49,7 @@ export default function BlockList( { className, __experimentalLayout } ) { | |||
}, [] ); | |||
|
|||
return ( | |||
<BlockNodes.Provider value={ blockNodes }> | |||
<> | |||
{ insertionPoint } | |||
<BlockPopover /> |
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.
After this and #31134, we can move the popover and insertion point out of the BlockList component.
}, [] ); | ||
return useCallback( ( element ) => { | ||
// Update the ref in the provider. | ||
ref.current = element; |
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.
I wonder if we could just set the element in the context here instead of using an intermediary "ref". I thought the "ref" was useful for useBlockRef, but it doesn't seem to be the case anyway.
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.
We could through useMergeRefs
, but we'd need to callback anyway as well, so this seems a bit simpler.
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.
I like this PR a lot, I like how it simplifies all these places where we rely on block elements. There are probably more.
@@ -24,7 +25,7 @@ function BlockEditorProvider( props ) { | |||
// Syncs the entity provider with changes in the block-editor store. | |||
useBlockSync( props ); | |||
|
|||
return children; | |||
return <BlockRefsProvider>{ children }</BlockRefsProvider>; |
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.
Since this is now a Provider inside the state provider, it makes me wonder whether we really need this new provider and whether we can just use the store to keep track of these refs.
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.
Hm, I'm not sure. Then we'd have refs and elements in the redux state?
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.
Is that an issue? 🤷♂️That doesn't bother me personally, it's not a part of the state that is meant to be serializable
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.
To clarify, it doesn't bother me as right now, I'm just wondering whether it's just the same thing and we could avoid the extra state/provider
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.
I can try, but we'd still keep the mutable maps because otherwise we're rerendering the editor too much on load
Description
Fixes #29475.
Fixes #29457.
This is sorely needed to be able to access the a block node by client ID that doesn't rely on querying the document and doesn't need
ownerDocument
. Currently, the skip to selected block button and colour panels are broken for the iframed site editor.useBlockRef
gets a ref that points to the current block node anduseBlockElement
return the element directly and updates whenever the element changes.We do currently provide block nodes, but it's limited to the selected block nodes and only works within the
BlockList
. This PR also moved the context to theBlockEditorProvider
so it can be accessed by all components.How has this been tested?
Screenshots
Types of changes
Checklist: