How to detect when a block is duplicated

Viewed 315

I want to give my blocks a unique ID that remains the same along post updates.

edit: class extends Component {
   constructor(props) {
      if(!props.blockID) this.props.setAttributes({ blockID: 'blk'+(new Date()).getTime() });
   }
}

But when the user duplicates de block, causes the ID being twice on the page.

I need some way to detect the duplication and give a new ID to the block.

Thanks.

2 Answers

I have done something similar before. The way I got it to work was to do two things:

  1. Save the id as a block attribute (so it stays the same across renders/post updates). If the block's id is undefined, it is a new block, so you can set the id.
  2. As each block renders, check its id against all the previous ids. If a block with that ID already exists, it is a duplicate.

Something like this should get you started:

let uniqueIds = [];

const ComponentEdit = ({
    attributes,
    setAttributes,
}) => {
    const {
        uuid,
    } = attributes;

    useEffect(() => {
        let id = uuid;

        if (!id || uniqueIds.includes(id)) {
            id = getUniqueIDFunc(); // Set your unique ID here

            setAttributes({uuid: id});
        }

        uniqueIds.push(id);
    }, []);
    
    return (
        <div id={ uuid }></div>
    );
};

I hope this would help You

import { createHigherOrderComponent } from '@wordpress/compose';
import { useEffect } from '@wordpress/element';
import { simpleHash } from '../../helpers/simple-hash';
import { v1 as uuidv1 } from 'uuid';
import { select } from '@wordpress/data';
import { addFilter } from '@wordpress/hooks';

const isBlockIdReserved = ( blockId, clientId ) => {
    const blocksClientIds = select( 'core/block-editor' ).getClientIdsWithDescendants();
    return blocksClientIds.some( ( _clientId ) => {
        const { blockId: _blockId } = select( 'core/block-editor' ).getBlockAttributes( _clientId );
        return clientId !== _clientId && blockId === _blockId;
    } );
};

const addBlockEditAttributes = createHigherOrderComponent( ( BlockEdit ) => {
    return ( props ) => {
        const { attributes, setAttributes, clientId } = props;

        const {
            blockId,
        } = attributes;

        const setFreshBlockId = () => {
            const freshBlockId = simpleHash( uuidv1() );
            setAttributes( {
                blockId: freshBlockId,
            } );
        };

        useEffect( () => {
            if ( ! blockId ) {
                setFreshBlockId();
                return;
            }

            if ( isBlockIdReserved( blockId, clientId ) ) {
                // eslint-disable-next-line no-console
                console.log( `Block with id '${ blockId }' already exists. Regenerating...`, blockId );
                setFreshBlockId();
            }
        }, [ blockId ] );

        return <BlockEdit { ...props } />;
    };
}, 'addBlockEditAttributes' );



addFilter(
    'editor.BlockEdit',
    'my-plugin/add-block-edit-attributes',
    addBlockEditAttributes
);

Related