-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
React methods are executed infinited times when block is inserted through a custom pattern #63909
Comments
There's also a report in trac of this - https://core.trac.wordpress.org/ticket/61592. Also noting some similarities with #63713. |
Here's an example plugin that can be run via the DevTools console. const { createElement: el, useEffect } = wp.element;
const { registerBlockType } = wp.blocks;
const { InnerBlocks, useBlockProps } = wp.blockEditor;
registerBlockType( 'test/block-infinity-and-beyond', {
apiVersion: 3,
title: 'Test: Infinity and Beyond',
icon: 'pets',
category: 'text',
attributes: {
id: {
type: 'string',
},
},
edit: function Edit( { clientId, setAttributes } ) {
const blockProps = useBlockProps();
// Effect dependencies are intentionally omitted.
useEffect( () => {
console.log( 'mounted', clientId );
setAttributes( { id: clientId } );
return () => {
console.log( 'unmounted', clientId );
};
}, [] );
return el(
'div',
{ ...blockProps },
el(
'strong',
null,
'Infinity and Beyond'
)
);
},
save() {
return null;
},
} ); |
@htmgarcia I think you should at least have some code like this, particularly when setting attributes in if (clientId !== attributes.blockID) {
setAttributes({ blockID: clientId });
}
That said, the core issue within the pattern block is still something to fix in the gutenberg codebase. |
Adding to the 6.6 board for consideration with a future point release and dropping into the 6.6 release leads channel for awareness. |
It seems to be related to the sync logic when you update the attribute programmatically 🤔 It will try to remove the existing block and insert it again, so it jumps into an infinite loop. |
It looks like regression is caused by this line in the Pattern block:
There's no infinite loop if I point |
@Mamaduka Yeah, this does seem to fix it, and I'm not seeing any issues with the functionality of the block. The It'd still be good to know if @ellatrix has any further feedback or reasons not to make that change. If you want to push a PR with the change I'd be happy to test/review. It'd also be good to see if the e2e tests for patterns pass as there's pretty good coverage. |
@talldan, I don't mind pushing a fix, but I would like to get more context around the original change first. |
I just left a comment there: link. I'm fine changing that line and see if tests still pass, but I must say I am not sure about the implications. |
I am pretty sure I asked about this line somewhere, but I can't find it now. If I remember correctly, this also came from a different PR that was a proof of concept. In any case, I don't know anything more, I think you should just try it, see what tests fail and test a bit manually. :) |
Description
Custom Gutenberg blocks that uses React native methods such as
componentDidMount()
can break the editor due an infinite loop. Only happens if the block is inserted through a custom pattern.Errors in console are:
Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
This started happening in WordPress 6.6.
In WordPress 6.5 this wasn't happening.
Step-by-step reproduction instructions
Create a custom plugin that will load our custom block that includes componentDidMount() and constructor() methods. If you have a ready custom plugin, you can just add these methods in the edit component too.
File structure of the custom plugin is as follows. Simply create those 2 files in an existing WordPress 6.6 site:
wp-content/plugins/custom-plugin/custom-plugin.php
wp-content/plugins/custom-plugin/block.js
The parts of the code we're analyzing here are
componentDidMount()
andconstructor()
fromEditComponent
class. I added on purpose a couple of log lines to observe in browser console when inserting "Custom Paragraph" block.Activate the custom plugin and test "Custom paragraph" block
Create a custom pattern
Convert the "Custom paragraph" block into a pattern by doing click in the 3-dots > Create pattern
Type a name and click "Add"
Then the screen will get stuck in the loading process and editor stop working
If you repeat the process by having the browser console opened, you'll see the logs for
componentDidMount()
andconstructor()
are outputted infinite times.The problem happens also when you try to insert the custom pattern (because pattern is created but editor can't insert into page).
Partial solution?
The culprit of the infinite loop according to logs points to
setAttributes()
method insidecomponentDidMount()
. If I add a check, the issue seems "solved", however this check is not needed when the block is inserted normally (not as a pattern), plus the logic of the block requires a unique value for blockID for every new instance, meaning theif()
is messing with it, particularly if I duplicate the block. The value for the clones will be the same (non unique).This is how 2 instances of the custom block looks like after duplicating the first one. Same value for blockID. So the fix is not good enough.
I wonder what changed in core to potentially cause an infinity execution of native React methods?
Screenshots, screen recording, code snippet
YouTube screencast
https://youtu.be/4B7XiLaWiOM
Environment info
Tested with and without Gutenberg plugin active. Same result.
Please confirm that you have searched existing issues in the repo.
Please confirm that you have tested with all plugins deactivated except Gutenberg.
The text was updated successfully, but these errors were encountered: