gutenberg
gutenberg copied to clipboard
The page jumps to top back when you scroll down, if paragraph block is selected in the custom child block (using innerBlock)
I'm not sure if it is a bug or not. But need a little help to solve the behavior issue.
I’ve developed two custom blocks — a parent block and a child block. When a user clicks a paragraph block inside the custom child block and scrolls down until the selected block is out of view, then the page jumps to top back.
To see this behavior in action, please open the video link:
How to prevent this automatic jumping behavior?
/* parent block */
import { backgroundColor, foregroundColor } from '../shared/settings';
const { registerBlockType } = wp.blocks;
const { __ } = wp.i18n;
const { useBlockProps, InnerBlocks } = wp.blockEditor;
const { createBlock } = wp.blocks;
const { Button } = wp.components;
const { dispatch, useSelect } = wp.data;
const blockName = "spa/child-block";
registerBlockType( 'spa/parent-block', {
title: 'SPA parent',
apiVersion: 3,
category: 'edhotels',
attributes: {
heading: {
type: "string"
}
},
allowedBlocks: [ blockName ],
icon: {
background: backgroundColor,
foreground: foregroundColor,
src: 'align-full-width',
},
edit: (props) => {
const { clientId } = props;
const { blockCount } = useSelect(select => {
return {
blockCount: select('core/block-editor').getBlockOrder(clientId).length
}
});
const addBlock = () => {
const addBlock = createBlock(blockName);
dispatch('core/block-editor').insertBlocks(addBlock, blockCount, clientId);
}
return (
<div { ...useBlockProps(
{
className: 'parent-block'
}
) }>
<div className="add-block-action">
<Button
isPrimary
onClick = { addBlock }
className="add-block-button"
>
{ __('Add a block', 'edhotels') }
</Button>
</div>
<InnerBlocks
template = {[[blockName]]}
// className = "parent-block"
allowedBlocks={ [blockName] }
templateLock={ false }
renderAppender={ false }
orientation = "horizontal"
/>
</div>
);
},
save: (props) => {
const { attributes } = props;
const { } = attributes;
return (
<div {...useBlockProps.save(
{
className: 'parent-block',
}
)}>
<InnerBlocks.Content />
</div>
);
}
});
/* child block */
import { backgroundColor, foregroundColor } from '../shared/settings';
const { registerBlockType, createBlocksFromInnerBlocksTemplate } = wp.blocks;
const { __ } = wp.i18n;
const {
useBlockProps,
useInnerBlocksProps,
InnerBlocks,
__experimentalBlockVariationPicker: BlockVariationPicker,
store: blockEditorStore,
} = wp.blockEditor;
const { Path, SVG } = wp.components;
const { dispatch, useSelect } = wp.data;
const variations = [
{
name: "one",
title: __("One"),
description: __("One"),
icon: (
<SVG
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"
viewBox="0 0 48 48"
>
<Path d="M0 10a2 2 0 0 1 2-2h44a2 2 0 0 1 2 2v28a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V10Z" />
</SVG>
),
// isDefault: true,
innerBlocks: [
["core/paragraph", {content: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}]
],
scope: ["inserter"],
},
{
name: "two",
title: __("Two"),
description: __("Two"),
icon: (
<SVG
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"
viewBox="0 0 48 48"
>
<Path d="M0 10a2 2 0 0 1 2-2h44a2 2 0 0 1 2 2v28a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V10Z" />
</SVG>
),
// isDefault: true,
innerBlocks: [
["core/paragraph", {content: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}],
["core/paragraph", {content: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}]
],
scope: ["inserter"],
},
{
name: "three",
title: __("Three"),
description: __("Three"),
icon: (
<SVG
xmlns="http://www.w3.org/2000/svg"
width="48"
height="48"
viewBox="0 0 48 48"
>
<Path d="M0 10a2 2 0 0 1 2-2h44a2 2 0 0 1 2 2v28a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V10Z" />
</SVG>
),
// isDefault: true,
innerBlocks: [
["core/paragraph", {content: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}],
["core/paragraph", {content: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}],
["core/paragraph", {content: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."}]
],
scope: ["inserter"],
}
];
registerBlockType('spa/child-block', {
title: 'SPA child',
apiVersion: 3,
category: 'edhotels',
parent: ['spa/parent-block'],
icon: {
background: backgroundColor,
foreground: foregroundColor,
src: 'align-full-width',
},
supports: {
html: true,
inserter: false,
reusable: false,
},
allowedBlocks: [ 'core/paragraph' ],
edit: (props) => {
const blockProps = useBlockProps( );
const { setAttributes, clientId } = props;
function EditContainer() {
return <section {...useBlockProps()}>
<InnerBlocks
template = {[['core/paragraph']]}
className = "block-slider-inner"
templateLock={ false }
renderAppender={ false }
orientation = "horizontal"
/>
</section>
}
const innerBlocks = useSelect(
(select) => select(blockEditorStore).getBlocks(clientId),
[clientId]
);
const hasInnerBlocks = innerBlocks.length > 0;
if (!hasInnerBlocks) {
return (
<div {...blockProps}>
<BlockVariationPicker
label="Section Variant"
variations={variations}
onSelect={(variation = variations[0]) => {
const { replaceInnerBlocks } = dispatch('core/block-editor');
if (variation.attributes) {
setAttributes(variation.attributes);
}
if (variation.innerBlocks) {
replaceInnerBlocks(
clientId,
createBlocksFromInnerBlocksTemplate(
variation.innerBlocks
),
false
);
}
}}
// allowSkip
/>
</div>
);
}
return (
<div {...blockProps}>
<EditContainer />
</div>
);
},
save: () => {
const blockProps = useBlockProps.save( );
const innerBlocksProps = useInnerBlocksProps.save( blockProps );
return <div { ...innerBlocksProps } />;
}
});
I see some issues in your code that I think are worth fixing, then letting us know if the issue still happens:
- The first (parent) block has a useSelect without a dependency array.
- For props like
templateandallowedBlocksa new array reference is passed on every render, you can define these as variables outside of your edit component (e.g. near whereblockNameis defined). - The
EditContainerfunction component is defined inline within another function component, which is an anti-pattern to avoid. This component will have a new reference on every render, so React will be unable to track it across renders as the same component that's being rendered, which will cause it to re-mount on every render. I don't think you needEditContainerto be a component, you can inline the code. Or extract it from function.
My guess is the last one is the cause of the bug.