Skip to content
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

Try improving ListView drag and drop performance by computing blocksData ahead of time #50210

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { useState, useCallback } from '@wordpress/element';
import { useState, useCallback, useRef } from '@wordpress/element';
import {
useThrottle,
__experimentalUseDropZone as useDropZone,
Expand Down Expand Up @@ -186,6 +186,7 @@ export function getListViewDropTarget( blocksData, position ) {
* @return {WPListViewDropZoneTarget} The drop target.
*/
export default function useListViewDropZone() {
const blocksData = useRef( null );
const {
getBlockRootClientId,
getBlockIndex,
Expand All @@ -199,64 +200,76 @@ export default function useListViewDropZone() {

const onBlockDrop = useOnBlockDrop( targetRootClientId, targetBlockIndex );

const draggedBlockClientIds = getDraggedBlockClientIds();
const throttled = useThrottle(
useCallback(
( event, currentTarget ) => {
const position = { x: event.clientX, y: event.clientY };
const isBlockDrag = !! draggedBlockClientIds?.length;
const getBlocksData = useCallback(
( eventTarget ) => {
const blockElements = Array.from(
eventTarget.querySelectorAll( '[data-block]' )
);

const blockElements = Array.from(
currentTarget.querySelectorAll( '[data-block]' )
);
const draggedBlockClientIds = getDraggedBlockClientIds();
const isBlockDrag = !! draggedBlockClientIds?.length;

const blocksData = blockElements.map( ( blockElement ) => {
const clientId = blockElement.dataset.block;
const isExpanded = blockElement.dataset.expanded === 'true';
const rootClientId = getBlockRootClientId( clientId );
return blockElements.map( ( blockElement ) => {
const clientId = blockElement.dataset.block;
const isExpanded = blockElement.dataset.expanded === 'true';
const rootClientId = getBlockRootClientId( clientId );

return {
clientId,
isExpanded,
rootClientId,
blockIndex: getBlockIndex( clientId ),
element: blockElement,
isDraggedBlock: isBlockDrag
? draggedBlockClientIds.includes( clientId )
: false,
innerBlockCount: getBlockCount( clientId ),
canInsertDraggedBlocksAsSibling: isBlockDrag
? canInsertBlocks(
draggedBlockClientIds,
rootClientId
)
: true,
canInsertDraggedBlocksAsChild: isBlockDrag
? canInsertBlocks( draggedBlockClientIds, clientId )
: true,
};
} );
return {
clientId,
isExpanded,
rootClientId,
blockIndex: getBlockIndex( clientId ),
element: blockElement,
isDraggedBlock: isBlockDrag
? draggedBlockClientIds.includes( clientId )
: false,
innerBlockCount: getBlockCount( clientId ),
canInsertDraggedBlocksAsSibling: isBlockDrag
? canInsertBlocks( draggedBlockClientIds, rootClientId )
: true,
canInsertDraggedBlocksAsChild: isBlockDrag
? canInsertBlocks( draggedBlockClientIds, clientId )
: true,
};
} );
},
[
canInsertBlocks,
getBlockCount,
getBlockIndex,
getBlockRootClientId,
getDraggedBlockClientIds,
]
);

const newTarget = getListViewDropTarget( blocksData, position );
const throttled = useThrottle(
useCallback( ( event ) => {
const position = { x: event.clientX, y: event.clientY };
const newTarget = getListViewDropTarget(
blocksData.current,
position
);

if ( newTarget ) {
setTarget( newTarget );
}
},
[ draggedBlockClientIds ]
),
if ( newTarget ) {
setTarget( newTarget );
}
}, [] ),
200
);

const ref = useDropZone( {
onDrop: onBlockDrop,
onDragStart( event ) {
blocksData.current = getBlocksData( event.currentTarget );
},
onDragOver( event ) {
// `currentTarget` is only available while the event is being
// handled, so get it now and pass it to the thottled function.
// https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
throttled( event, event.currentTarget );
throttled( event );
},
onDragEnd() {
blocksData.current = null;
throttled.cancel();
setTarget( null );
},
Expand Down