• Resolved ftroitero

    (@ftroitero)


    I am working on a custom block type for the WordPress Gutemberg editor.

    The block type displays and saves content and a date.

    I’m trying to save the creation date for every block by setting a postDate value on the block type attributes. And I could successfully save this value using the save function.

    However, the value is not updated on every block creation, it stays the same and every block has the same postDate value (the creation of the first block) passed to the database.

    I need it to be updated so it can be saved in the “save” function. It needs to be updated only once, when a block is created.

    This is the workflow I’m trying to achieve:

    User creates a block / user edits the block / edits and hits the “Update” button (preferably the first option) -> postDate for that block is saved only once

    User creates a different block -> same process occurs. Each block has its postDate value saved. The value can not be altered by subsequent edits

    here is the function:

    registerBlockType(metadata.name, {
        attributes: {
            content: {
                type: "string",
                source: "html",
                selector: "h2",
            },
            postDate: {
                type: "string",
                default: moment().tz("Europe/Paris").locale("fr").format(), 
            },
            blockId: {
                type: "string",
            },
        },
    
        edit({ attributes, setAttributes, clientId }) {
            const blockProps = useBlockProps();
    
            const { postDate, blockId } = attributes;
    
            React.useEffect(() => {
                if (!blockId) {
                    setAttributes({ blockId: clientId });
                }
            }, []);
    
    
            const TEMPLATE = [["core/paragraph", {}]];
    
            const ALLOWED_BLOCKS = useMemo(
                () =>
                    wp.blocks
                        .getBlockTypes()
                        .filter((block) => block.name !== metadata.name)
                        .map((block) => block.name),
                [metadata.name]
            );
    
            return (
                <div className="wp-post-live-block">
                    <time dateTime={postDate}>
                        {moment(postDate).format("D/M H:mm:ss")}
                    </time>
                    <RichText
                        {...blockProps}
                        tagName="h2"
                        value={attributes.content}
                        onChange={(content) => setAttributes({ content })}
                        placeholder={__("Add title")}
                    />
                    <InnerBlocks template={TEMPLATE} allowedBlocks={ALLOWED_BLOCKS} />
                </div>
            );
        },
    
        save({ attributes }) {
            const blockProps = useBlockProps.save();
            const { postDate, blockId } = attributes;
    
            return (
                <div data-timestamp={postDate} id={blockId} className="wp-post-live-block">
                    <RichText.Content
                        {...blockProps}
                        tagName="h2"
                        value={attributes.content}
                    />
                    <InnerBlocks.Content />
                </div>
            );
        },
    });

    I’ve tried setting the postDate value on the useEffect tool, inside the if (!blockId) condition. However, this makes the function try to update the value on every render.

    Where can I hook the setAttribute(postDate) so that it updates only once, when the block is created?

    • This topic was modified 1 year, 10 months ago by ftroitero.
    • This topic was modified 1 year, 10 months ago by ftroitero.
Viewing 2 replies - 1 through 2 (of 2 total)
  • If I understood correctly, you want the postDate value to be assigned to the current date at the moment the user adds the block to the page, and you don’t want it to be changed when the user modifies the content of the block.

    I think to achieve this you can’t assign a default value to the postDate attribute, in the attributes declaration. Instead, you should set the value in the useEffect, unless it’s already set:

    attributes:
        postDate: {
            type: "string",
        },
        // ...
    }
    
    React.useEffect(() => {
        if (!blockId) {
            setAttributes({ blockId: clientId });
        }
        if (!postDate) {
            setAttributes({ postDate: moment().tz("Europe/Paris").locale("fr").format() });
        }
    }, []);
    
    Thread Starter ftroitero

    (@ftroitero)

    That is the right answer.

    Null value at the start => set the value only if its null, inside a useEffect hook with empty dependency array.

    3 years trying and I still can’t figure out how React hooks work ???♀?.

    Obrigado pela ajuda

Viewing 2 replies - 1 through 2 (of 2 total)
  • The topic ‘Custom block type in Gutemberg , setting and saving values on block creation’ is closed to new replies.