Skip to content

Commit

Permalink
Split select in getFieldsList hook
Browse files Browse the repository at this point in the history
  • Loading branch information
SantosGuillamot committed Sep 24, 2024
1 parent 436015f commit 9fef8fb
Showing 1 changed file with 43 additions and 44 deletions.
87 changes: 43 additions & 44 deletions packages/block-editor/src/hooks/block-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ import { store as blockEditorStore } from '../store';

const { DropdownMenuV2 } = unlock( componentsPrivateApis );

const EMPTY_OBJECT = {};

const useToolsPanelDropdownMenuProps = () => {
const isMobile = useViewportMatch( 'medium', '<' );
return ! isMobile
Expand Down Expand Up @@ -192,50 +190,51 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
const bindableAttributes = getBindableAttributes( blockName );
const dropdownMenuProps = useToolsPanelDropdownMenuProps();

// `useSelect` is used purposely here to ensure `getFieldsList`
// is updated whenever there are updates in block context.
// `source.getFieldsList` may also call a selector via `registry.select`.
const _fieldsList = {};
const { fieldsList, canUpdateBlockBindings } = useSelect(
( select ) => {
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
return EMPTY_OBJECT;
}
const { getBlockBindingsSources } = unlock( blocksPrivateApis );
const registeredSources = getBlockBindingsSources();
Object.entries( registeredSources ).forEach(
( [ sourceName, { getFieldsList, usesContext } ] ) => {
if ( getFieldsList ) {
// Populate context.
const context = {};
if ( usesContext?.length ) {
for ( const key of usesContext ) {
context[ key ] = blockContext[ key ];
}
}
const sourceList = getFieldsList( {
registry,
context,
} );
// Only add source if the list is not empty.
if ( Object.keys( sourceList || {} ).length ) {
_fieldsList[ sourceName ] = { ...sourceList };
const { canUpdateBlockBindings } = useSelect( ( select ) => {
return {
canUpdateBlockBindings:
select( blockEditorStore ).getSettings().canUpdateBlockBindings,
};
}, [] );

/**
* Create new selector for fieldsList to avoid unnecessary re-renders.
* See: https://github.com/WordPress/gutenberg/pull/64072#discussion_r1764693730
*
* `useSelect` is used purposely here to ensure `getFieldsList` is updated
* whenever there are updates in block context.
* `source.getFieldsList` may also call a selector via `registry.select`.
*/
const fieldsList = useSelect( () => {
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
return;
}
const _fieldsList = {};
const { getBlockBindingsSources } = unlock( blocksPrivateApis );
const registeredSources = getBlockBindingsSources();
Object.entries( registeredSources ).forEach(
( [ sourceName, { getFieldsList, usesContext } ] ) => {
if ( getFieldsList ) {
// Populate context.
const context = {};
if ( usesContext?.length ) {
for ( const key of usesContext ) {
context[ key ] = blockContext[ key ];
}
}
const sourceList = getFieldsList( {
registry,
context,
} );
// Only add source if the list is not empty.
if ( Object.keys( sourceList || {} ).length ) {
_fieldsList[ sourceName ] = { ...sourceList };
}
}
);
return {
fieldsList:
Object.values( _fieldsList ).length > 0
? _fieldsList
: EMPTY_OBJECT,
canUpdateBlockBindings:
select( blockEditorStore ).getSettings()
.canUpdateBlockBindings,
};
},
[ blockContext, bindableAttributes, registry ]
);
}
);
return Object.values( _fieldsList ).length > 0 && { ..._fieldsList };
}, [ blockContext, bindableAttributes, registry ] );
// Return early if there are no bindable attributes.
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
return null;
Expand All @@ -254,7 +253,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {

// Lock the UI when the user can't update bindings or there are no fields to connect to.
const readOnly =
! canUpdateBlockBindings || ! Object.keys( fieldsList ).length;
! canUpdateBlockBindings || ! Object.keys( fieldsList || {} ).length;

if ( readOnly && Object.keys( filteredBindings ).length === 0 ) {
return null;
Expand Down

0 comments on commit 9fef8fb

Please sign in to comment.