-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Not possible to change allowedBlocks dynamically #14515
Comments
Also, it cannot be added on the first page. Currently not 100% bulletproof: WordPress/gutenberg#14515
@jorgefilipecosta Heya, since we briefly discussed this on Slack the other day (see archive link in the issue above) - do you perhaps have any suggestions for me on how to best approach this? I'd love to try to find the root cause of the issue. Are there perhaps some tests for this functionality somewhere? |
Hi @swissspidy, I am not being able to replicate this problem. I added a Container block I verified that the allow blocks change after adding two blocks. Watching your example allowedBlocks={ isFirstBlock ? [ 'my/block-a' ] : [ 'my/block-b' ] }, it seems you are passing a new array referrence on each reference, could you try passing the same references ? (maybe it is related to the problem). |
Interesting. Actually my code is more like this: import { LIST_A, LIST_B } from './constants.js';
export default withSelect( ( select, { clientId } ) => {
const { getBlockOrder } = select( 'core/editor' );
return {
isFirstBlock: getBlockOrder().indexOf( clientId ) === 0,
};
} )( MyBlockEdit );
// ...
// In MyBlockEdit's edit() function:
<InnerBlocks template={ myTemplate } allowedBlocks={ isFirstBlock ? LIST_A : LIST_B } /> I just shortened it for the example here. The current actual code can be found here: https://github.com/ampproject/amp-wp/blob/3e7050ac1e03d0b69d2ceff14f01a0ff0f7d91db/assets/src/blocks/amp-story-page/edit.js#L339-L367 It's a bit different than that example at the moment, but I also just quickly changed it to that - still not working. I'll take another look soon though to see if I am missing something. |
## Description This PR adds a simple end 2 end test that makes sure allowed blocks inside a parent block can be changed dynamically depending on some condition e.g: the number of child's the parent contains. ## How has this been tested? We just need to make sure the test cases pass. Related: #14515
I'm also facing the same issue. But my use case is to update the blocks within the template and their attributes. Below is the snippet that I'm trying to run. https://gist.github.com/desaiuditd/c6ef602b86afa8f22034ab043766517f In a nutshell it's allowing below use case.
@swissspidy Did you ever find any solution on this? |
Hi @swissspidy, I made another test similar to yours where allows blocks depends on if the block is the first block or not: https://gist.github.com/jorgefilipecosta/40efacc3f573b666afd89df461a83b69 Is there any update to the issue? Did you found the root cause, or it is still happening in the last version of Gutenberg? When trying the block, I provided in your environment the problem persists? Hi @desaiuditd the issue you are describing with templates is a different one. Templates are just a prefilling mechanism for empty InnerBlock areas. When the template changes if the InnerBlocks area is not empty there should be no expectation an update will happen. In this comment #15965 (comment), I wrote an expanded explanation, and I suggest possible alternatives. I hope you find it helpful. |
Thanks for testing @jorgefilipecosta, I really appreciate it! In your example code, is At some point we ended up replacing the inserter with our own patched version because of this, so I am not sure if the original issue is still happening. I will have to check it out. One workaround we added was in addition to using the unstable |
Related: #16560 |
Is this issue still relevant? cc @jorgefilipecosta |
Coming back to this. It is still not possible to change I tested this on WordPress vanilla version 5.9.3 without Gutenberg plugin, as well as with Gutenberg plugin version 13.1.0. I get below warning on the browser console as well.
This block of code seems to be the culprit. Seems like, the Introduced in this PR #30311. Merged in version 10.4. So likely to happen in all the versions after that. Even in WordPress core. @ellatrix Tagging you, just in case you have any insight on this. Below is my reproducible code. edit.js
The error would occur as soon as I add a third child block inside the inner block. |
So the likely fix is to wrap the
|
I'm having the same issue in WordPress 6.1.1 (also tested in Gutenberg 15.1.0), and having dug around a bit would like to suggest a fix, and a workaround. I think the root of the problem is in packages/block-editor/src/components/inner-blocks/use-nested-settings-update.js. // Memoize as inner blocks implementors often pass a new array on every
// render.
const _allowedBlocks = useMemo( () => allowedBlocks, allowedBlocks ); which was added in #30311 by @ellatrix This code calls useMemo incorrectly, as according to https://beta.reactjs.org/reference/react/useMemo "The list of dependencies must have a constant number of items and be written inline like [dep1, dep2, dep3]. React will compare each dependency with its previous value using the Object.is comparison algorithm." And of course the allowedBlocks array can change size! The reason that allowedBlocks won't sometimes change dynamically is that useMemo only compares the previous and current dependency arrays up until the smallest size to determine if they are different, so to it ['block1','block2'] and ['block1'] are the same (and I think [] is the same as everything), so it returns the memoized value - hence no change to allowed blocks. I'm guessing useMemo was added because people are doing <InnerBlocks allowedBlocks={ ['block1'] } /> which sends a new reference every render, which causes updates even if the contents haven't changed. If that's the case then the following code calls useMemo correctly and should achieve the desired result, and I think fix this issue: const _allowedBlocks = useMemo( () => allowedBlocks, [ allowedBlocks?.toString() ] ); I'm assuming here that allowedBlocks can be undefined or an array. An alternative would be Note that const _allowedBlocks = useMemo( () => allowedBlocks, [ allowedBlocks ] ); won't work because I modified this code in wp-includes\js\dist\block-editor.js and ran with SCRIPT_DEBUG, and with this naive testing it seems to work - at least the allowed blocks are changing correctly. I managed to work around this issue by making sure useMemo thinks the allowed blocks arrays are different by having the arrays not match up to the smallest array size. Of course the easiest way to do that is to change the first element: const ALLOWED_BLOCKS_1 = ['core/paragraph','core/image'];
const ALLOWED_BLOCKS_2 = ['core/image'];
function Edit() ...
allowedBlocks={ condition ? ALLOWED_BLOCKS_1 : ALLOWED_BLOCKS_2 }
Note: You might want to pass the same allowedBlocks and just modify the elements. That seems to work but you get the side effect that it comes up as allowed, but you can't actually add it. |
Hi, I'm having the same issue, any clue to fix it. I have a props if toggled then render ALLOWED_BLOCKS_1 else ALLOWED_BLOCKS_2 const ALLOWED_BLOCKS_1 = ['core/paragraph','core/image']; |
Thank you all for the extensive debugging and insights provided, I proposed a fix at #53943. |
(Previous discussion on Slack)
Describe the bug
Background: I have a block type A that uses the
InnerBlocks
component with a limited list ofallowedBlocks
. I now want to limit the inner blocks in a way that I can insert block type B only once withinInnerBlocks
. Overall, in the whole post, it can occur multiple times though.One suggestion was to modify
allowedBlocks
dynamically. That's what I am now doing, but currently fail to do so.I want to change
allowedBlocks
depending on some props, e.g. whether the block is the first one in the block order and whether it has already been added to the page.Unfortunately this doesn't seem to be possible at the moment.
To Reproduce
Given a block type with code like this:
Create 2 blocks of this type and notice that you're still able to insert both
my/block-a
andmy/block-b
in each.You might even run into https://reactjs.org/docs/error-decoder.html/?invariant=185 at this point.
You can verify that
allowedBlocks
changes by usingwp.data.select( 'core/editor' ).getBlockListSettings()
in dev tools.At the same time, the result of
wp.data.select( 'core/editor' ).canInsertBlockType()
does not seem to change.That selector uses memoization, although it should change when
allowedBlocks
changes. Apparently it doesn't.Expected behavior
It should be possible to dynamically filter
allowedBlocks
.It should be possible to limit a block to be only used once within a parent block.
Additional context
The text was updated successfully, but these errors were encountered: