blkhatpersian
blkhatpersian

Reputation: 437

Calling setAttributes() in Gutenberg Block causes bad setState() error in Editor Mode

In Editor Mode in Wordpress, I see a console error from React when initially rendering my Gutenberg block. Any further changes to the block does not cause the issue.

The exact error is: "Cannot update a component (EditorProvider) while rendering a different component (edit). To locate the bad setState() call inside edit, follow the stack trace".

My original problem was in a function where I retrieved Wordpress User Data and then set it to the attributes. I found out it can occur on a single call though. Ex: I added the line that causes the issue in the Edit return function:

setAttributes({userGravatarUrl:'http://www.gravatar.com/avatar/?d=mp'});

This is the first time I have attempted to use setAttributes() outside of an onChange property in another component/block.

The attribute name is correct so I know that is not the issue. Is this an error I should ignore? Or how can I remedy this?

My full code below:

export default function Edit( { attributes, setAttributes } ) {
    const blockProps = useBlockProps();
    setAttributes({userGravatarUrl:'http://www.gravatar.com/avatar/?d=mp'});
    const divStyle = {
        color: attributes.textColor,
        backgroundColor: attributes.backgroundColor,
      };
    return (
        <div { ...blockProps } style={divStyle}>
            <div className='block-section'>
                { attributes.displayGravatar && 
                <img src = {attributes.userGravatarUrl}/>
                }
            </div>
        </div>
        );
}

block.json

        "displayGravatar": {
            "type": "boolean",
            "default": true
        },
        "displayUserName":{
            "type": "boolean",
            "default": true
        },
        "displayBio":{
            "type": "boolean",
            "default": true
        },
        "selectedUserId":{
            "type": "string"
        },
        "backgroundColor":{
            "type": "string",
            "default": "#FFFFFF"
        },
        "textColor":{
            "type": "string",
            "default": "#000000"
        },
        "userGravatarUrl":{
            "type": "string"
        },
        "userBio":{
            "type": "string"
        },
        "userName":{
            "type": "string"
        }
    }```

Upvotes: 1

Views: 1291

Answers (1)

S.Walsh
S.Walsh

Reputation: 3699

Calling setAttributes() in Edit() before the return statement causes the "bad setState()" call by trying to set state while rendering another component. While it may seem like a harmless warning and everything appears like its working, many of these bad setState calls eventually leads to performance degradation then app crashes.

To assign a default value to your userGravatarUrl attribute inside Edit(), update your code to use object destructing in ES6 on the incoming attributes:

edit.js

export default function Edit({ attributes, setAttributes }) {
    const blockProps = useBlockProps();

    const {
        backgroundColor,
        displayGravatar,
        textColor,
        userGravatarUrl = "http://www.gravatar.com/avatar/?d=mp"
    } = attributes;

    const divStyle = {
        color: textColor,
        backgroundColor: backgroundColor,
    };

    return (
        <div {...blockProps} style={divStyle}>
            <div className='block-section'>
                {displayGravatar &&
                    <img src={userGravatarUrl} />
                }
            </div>
        </div>
    );
}

Object destructing can also improve code readability as attributes.nameOfAttribute becomes nameOfAttribute. By avoiding "bad setState()" calls today, your tomorrow will be easier..

Upvotes: 2

Related Questions