Skip to content

Commit

Permalink
Perf: batch block list settings in single action
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed May 2, 2024
1 parent 907c8b1 commit 364180c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { useLayoutEffect, useMemo, useState } from '@wordpress/element';
import { useDispatch, useRegistry } from '@wordpress/data';
import { useRegistry } from '@wordpress/data';
import deprecated from '@wordpress/deprecated';
import isShallowEqual from '@wordpress/is-shallow-equal';

Expand All @@ -11,6 +11,7 @@ import isShallowEqual from '@wordpress/is-shallow-equal';
*/
import { store as blockEditorStore } from '../../store';
import { getLayoutType } from '../../layouts';
import { unlock } from '../../lock-unlock';

/** @typedef {import('../../selectors').WPDirectInsertBlock } WPDirectInsertBlock */

Expand Down Expand Up @@ -69,7 +70,6 @@ export default function useNestedSettingsUpdate(
// Instead of adding a useSelect mapping here, please add to the useSelect
// mapping in InnerBlocks! Every subscription impacts performance.

const { updateBlockListSettings } = useDispatch( blockEditorStore );
const registry = useRegistry();

// Implementors often pass a new array on every render,
Expand Down Expand Up @@ -155,21 +155,18 @@ export default function useNestedSettingsUpdate(
// we batch all the updatedBlockListSettings in a single "data" batch
// which results in a single re-render.
if ( ! pendingSettingsUpdates.get( registry ) ) {
pendingSettingsUpdates.set( registry, [] );
pendingSettingsUpdates.set( registry, new Map() );
}
pendingSettingsUpdates
.get( registry )
.push( [ clientId, newSettings ] );
pendingSettingsUpdates.get( registry ).set( clientId, newSettings );
window.queueMicrotask( () => {
if ( pendingSettingsUpdates.get( registry )?.length ) {
registry.batch( () => {
pendingSettingsUpdates
.get( registry )
.forEach( ( args ) => {
updateBlockListSettings( ...args );
} );
pendingSettingsUpdates.set( registry, [] );
} );
if ( pendingSettingsUpdates.get( registry ).size ) {
const { batchUpdateBlockListSettings } = unlock(
registry.dispatch( blockEditorStore )
);
batchUpdateBlockListSettings(
pendingSettingsUpdates.get( registry )
);
pendingSettingsUpdates.set( registry, new Map() );
}
} );
}, [
Expand All @@ -183,7 +180,6 @@ export default function useNestedSettingsUpdate(
__experimentalDirectInsert,
captureToolbars,
orientation,
updateBlockListSettings,
layout,
registry,
] );
Expand Down
14 changes: 14 additions & 0 deletions packages/block-editor/src/store/private-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ const privateSettings = [
'blockInspectorAnimation',
];

/**
* Action that changes the nested settings of a given block.
*
* @param {Map} settingsByClientId A map of block client IDs to their settings.
*
* @return {Object} Action object
*/
export function batchUpdateBlockListSettings( settingsByClientId ) {
return {
type: 'BATCH_UPDATE_BLOCK_LIST_SETTINGS',
settingsByClientId,
};
}

/**
* Action that updates the block editor settings and
* conditionally preserves the experimental ones.
Expand Down
13 changes: 13 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1769,6 +1769,19 @@ export const blockListSettings = ( state = {}, action ) => {
[ clientId ]: action.settings,
};
}

case 'BATCH_UPDATE_BLOCK_LIST_SETTINGS': {
const { settingsByClientId } = action;
const updates = {};
for ( const [ clientId, _settings ] of settingsByClientId ) {
if ( ! fastDeepEqual( state[ clientId ], _settings ) ) {
updates[ clientId ] = _settings;
}
}
return Object.keys( updates ).length
? { ...state, ...updates }
: state;
}
}
return state;
};
Expand Down

0 comments on commit 364180c

Please sign in to comment.