Skip to content

Commit d627aa5

Browse files
Split select in getFieldsList hook
1 parent d66d138 commit d627aa5

File tree

1 file changed

+43
-44
lines changed

1 file changed

+43
-44
lines changed

packages/block-editor/src/hooks/block-bindings.js

+43-44
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ import { store as blockEditorStore } from '../store';
3131

3232
const { DropdownMenuV2 } = unlock( componentsPrivateApis );
3333

34-
const EMPTY_OBJECT = {};
35-
3634
const useToolsPanelDropdownMenuProps = () => {
3735
const isMobile = useViewportMatch( 'medium', '<' );
3836
return ! isMobile
@@ -192,50 +190,51 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
192190
const bindableAttributes = getBindableAttributes( blockName );
193191
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
194192

195-
// `useSelect` is used purposely here to ensure `getFieldsList`
196-
// is updated whenever there are updates in block context.
197-
// `source.getFieldsList` may also call a selector via `registry.select`.
198-
const _fieldsList = {};
199-
const { fieldsList, canUpdateBlockBindings } = useSelect(
200-
( select ) => {
201-
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
202-
return EMPTY_OBJECT;
203-
}
204-
const { getBlockBindingsSources } = unlock( blocksPrivateApis );
205-
const registeredSources = getBlockBindingsSources();
206-
Object.entries( registeredSources ).forEach(
207-
( [ sourceName, { getFieldsList, usesContext } ] ) => {
208-
if ( getFieldsList ) {
209-
// Populate context.
210-
const context = {};
211-
if ( usesContext?.length ) {
212-
for ( const key of usesContext ) {
213-
context[ key ] = blockContext[ key ];
214-
}
215-
}
216-
const sourceList = getFieldsList( {
217-
registry,
218-
context,
219-
} );
220-
// Only add source if the list is not empty.
221-
if ( Object.keys( sourceList || {} ).length ) {
222-
_fieldsList[ sourceName ] = { ...sourceList };
193+
const { canUpdateBlockBindings } = useSelect( ( select ) => {
194+
return {
195+
canUpdateBlockBindings:
196+
select( blockEditorStore ).getSettings().canUpdateBlockBindings,
197+
};
198+
}, [] );
199+
200+
/**
201+
* Create new selector for fieldsList to avoid unnecessary re-renders.
202+
* See: https://github.com/WordPress/gutenberg/pull/64072#discussion_r1764693730
203+
*
204+
* `useSelect` is used purposely here to ensure `getFieldsList` is updated
205+
* whenever there are updates in block context.
206+
* `source.getFieldsList` may also call a selector via `registry.select`.
207+
*/
208+
const fieldsList = useSelect( () => {
209+
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
210+
return;
211+
}
212+
const _fieldsList = {};
213+
const { getBlockBindingsSources } = unlock( blocksPrivateApis );
214+
const registeredSources = getBlockBindingsSources();
215+
Object.entries( registeredSources ).forEach(
216+
( [ sourceName, { getFieldsList, usesContext } ] ) => {
217+
if ( getFieldsList ) {
218+
// Populate context.
219+
const context = {};
220+
if ( usesContext?.length ) {
221+
for ( const key of usesContext ) {
222+
context[ key ] = blockContext[ key ];
223223
}
224224
}
225+
const sourceList = getFieldsList( {
226+
registry,
227+
context,
228+
} );
229+
// Only add source if the list is not empty.
230+
if ( Object.keys( sourceList || {} ).length ) {
231+
_fieldsList[ sourceName ] = { ...sourceList };
232+
}
225233
}
226-
);
227-
return {
228-
fieldsList:
229-
Object.values( _fieldsList ).length > 0
230-
? _fieldsList
231-
: EMPTY_OBJECT,
232-
canUpdateBlockBindings:
233-
select( blockEditorStore ).getSettings()
234-
.canUpdateBlockBindings,
235-
};
236-
},
237-
[ blockContext, bindableAttributes, registry ]
238-
);
234+
}
235+
);
236+
return Object.values( _fieldsList ).length > 0 && { ..._fieldsList };
237+
}, [ blockContext, bindableAttributes, registry ] );
239238
// Return early if there are no bindable attributes.
240239
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
241240
return null;
@@ -254,7 +253,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
254253

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

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

0 commit comments

Comments
 (0)