2

Is there a way to detect when the position of a block has changed? I am trying to do something when a block is moved.

I'm trying:

var blockIndex = wp.data.select( "core/block-editor" ).getBlockIndex( clientId );
const [ index, setIndex ] = useState(blockIndex);

useEffect( () => {
  console.log('Block moved');
}, [ blockIndex ] );

1 Answer 1

2

I don't know if there's an event or Gutenberg hook like blockMove or blockIndexChange, but you can use subscribe() from the @wordpress/data package to listen to the block index changes.

Working Example using hooks

  • WordPress dependencies:

    import { useBlockProps } from '@wordpress/block-editor';
    import { useState, useEffect } from '@wordpress/element';
    import { useSelect, subscribe } from '@wordpress/data';
    
  • The block's edit() function:

    function edit( { clientId } ) {
        const { getBlockIndex } = useSelect( 'core/block-editor' );
    
        // Set initial index.
        const [ currentBlockIndex, setBlockIndex ] = useState( getBlockIndex( clientId ) );
    
        // Subscribe once this block has been attached to the DOM.
        useEffect( () => {
            // Listen to block index changes and set the current index if necessary.
            // When you're done listening, just call unsubscribe().
            const unsubscribe = subscribe( () => {
                const blockIndex = getBlockIndex( clientId );
    
                if ( currentBlockIndex !== blockIndex ) {
                    console.log( `block move detected; from index ${ currentBlockIndex} to ${ blockIndex }` );
                    setBlockIndex( blockIndex ); // update current index
                }
            } );
    
            console.log( `subscribed; clientId is ${ clientId }` );
    
            // Unsubscribe; for example once this block is removed from the editor.
            return function cleanup() {
                unsubscribe();
                console.log( `unsubscribed - stopped listening to index changes; clientId is ${ clientId }` );
            };
        }, [ clientId, currentBlockIndex ] ); // note the currentBlockIndex
    
        return (
            <div { ...useBlockProps() }>
                Current block index: { currentBlockIndex }
            </div>
        );
    }
    

    So the useEffect callback will be called when the block is explicitly moved or that its index changed because another block was moved to the above block's current position.

You can also see my answer here for an example outside an edit function, which uses wp.domReady() and adds a block style once the current post type is determined.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.