The problem: whenever I type something in Advanced->Additional Classes in Gutenberg editor and save the page/post and refresh, those classes disappear. I logged props.className in edit
function. It logs the value as expected when I type the class name in the Advanced->Additional Classes field. The problem occurs when I save the post after inputting the class name and refresh the page. I followed the exact same method in other blocks I created and they work just fine.
The Code:
edit: (props) => {
const {attributes, setAttributes} = props;
const headingBgOverlay = Util.getBgOverlay(attributes, 'heading');
const bodyBgOverlay = Util.getBgOverlay(attributes, 'body');
useEffect(() => {
setAttributes({blockId: Util.guidGenerator()});
}, []);
useEffect(() => {
console.log(props)
console.log(props.className)
console.log(attributes.className)
setAttributes({headingBgOverlay});
setAttributes({bodyBgOverlay});
}, [attributes]);
return (
<Fragment>
<Fragment>
<style>
{listIconCss(attributes)}
</style>
<div className={"atbs atbs-pricing-table " + props.className}
id={'atbs-pricing-table-' + attributes.blockId}>
<div className="plan"
style={{...planCss(attributes)}}>
<div className="head" style={{...titleCss(attributes)}}>
<RichText style={{...titleTypographyCss(attributes)}} tagName="h2" className={'m-0'}
value={attributes.title}
onChange={(title) => setAttributes({title})}
placeholder={__('Plan name', 'attire-blocks')}/>
</div>
<div className='atbs_pricing_table_body'>
<RichText
style={{...descrCss(attributes)}}
className={'description'} tagName="p" value={attributes.description}
onChange={(description) => setAttributes({description})}
placeholder={__('Description...', 'attire-blocks')}/>
<div className="price" style={{...priceCss(attributes)}}>
<RichText style={{fontSize: (attributes.priceFontSize / 2) + 'px'}}
className={'symbol'}
tagName="span" value={attributes.symbol}
onChange={(symbol) => setAttributes({symbol})}
placeholder={__('$')}/>
<RichText className={'amount'}
tagName="span" value={attributes.price}
onChange={(price) => setAttributes({price})}
placeholder={__('99.99')}/>
{attributes.recurring && <RichText
style={{fontSize: `${attributes.descrFontSize}${attributes.descrFontSizeUnit}`}}
tagName="span" value={attributes.recurringTime}
className="recurring"
onChange={(value) => setAttributes({recurringTime: value})}
placeholder={__('/month', 'attire-blocks')}/>}
</div>
{attributes.showFeatures && <RichText
style={{...listCss(attributes)}}
multiline="li"
tagName="ul"
className="features"
onChange={(nextValues) => setAttributes({features: nextValues})}
value={attributes.features}
placeholder={__('Write list…', 'attire-blocks')}
/>}
<InnerBlocks allowedBlocks={['attire-blocks/buttons']}
template={[['attire-blocks/buttons', {
buttonAlignment: 'center'
}]]}
templateLock="all"/>
</div>
</div>
</div>
</Fragment>
</Fragment>
);
},
save: ({attributes, className}) => {
//const {attributes} = props;
return (
<Fragment>
<style>
{listIconCss(attributes)}
</style>
<div className={"atbs atbs-pricing-table " + className}
id={'atbs-pricing-table-' + attributes.blockId}>
<div className="plan"
style={{...planCss(attributes)}}>
{attributes.title &&
<div className="head" style={{...titleCss(attributes)}}>
<RichText.Content style={{...titleTypographyCss(attributes)}} tagName="h2" className={'m-0'}
value={attributes.title}/>
</div>}
<div className='atbs_pricing_table_body'>
{attributes.description &&
<RichText.Content
style={{...descrCss(attributes)}}
className={'description'} tagName="p" value={attributes.description}/>}
<div className="price" style={{...priceCss(attributes)}}>
<RichText.Content style={{fontSize: (attributes.priceFontSize / 2) + 'px'}}
className={'symbol'} tagName="span" value={attributes.symbol}/>
<RichText.Content
style={{
color: attributes.bodyTextColor,
fontSize: (attributes.priceFontSize) + 'px'
}}
className={'amount'}
tagName="span" value={attributes.price}/>
{attributes.recurring && <RichText.Content
style={{fontSize: `${attributes.descrFontSize}${attributes.descrFontSizeUnit}`}}
className="recurring"
tagName="span" value={attributes.recurringTime}/>}
</div>
</div>
{attributes.showFeatures && <RichText.Content
style={{...listCss(attributes)}}
className={'features'}
tagName="ul" value={attributes.features}/>}
<InnerBlocks.Content/>
</div>
</div>
</Fragment>
);
}
});
The problem: whenever I type something in Advanced->Additional Classes in Gutenberg editor and save the page/post and refresh, those classes disappear. I logged props.className in edit
function. It logs the value as expected when I type the class name in the Advanced->Additional Classes field. The problem occurs when I save the post after inputting the class name and refresh the page. I followed the exact same method in other blocks I created and they work just fine.
The Code:
edit: (props) => {
const {attributes, setAttributes} = props;
const headingBgOverlay = Util.getBgOverlay(attributes, 'heading');
const bodyBgOverlay = Util.getBgOverlay(attributes, 'body');
useEffect(() => {
setAttributes({blockId: Util.guidGenerator()});
}, []);
useEffect(() => {
console.log(props)
console.log(props.className)
console.log(attributes.className)
setAttributes({headingBgOverlay});
setAttributes({bodyBgOverlay});
}, [attributes]);
return (
<Fragment>
<Fragment>
<style>
{listIconCss(attributes)}
</style>
<div className={"atbs atbs-pricing-table " + props.className}
id={'atbs-pricing-table-' + attributes.blockId}>
<div className="plan"
style={{...planCss(attributes)}}>
<div className="head" style={{...titleCss(attributes)}}>
<RichText style={{...titleTypographyCss(attributes)}} tagName="h2" className={'m-0'}
value={attributes.title}
onChange={(title) => setAttributes({title})}
placeholder={__('Plan name', 'attire-blocks')}/>
</div>
<div className='atbs_pricing_table_body'>
<RichText
style={{...descrCss(attributes)}}
className={'description'} tagName="p" value={attributes.description}
onChange={(description) => setAttributes({description})}
placeholder={__('Description...', 'attire-blocks')}/>
<div className="price" style={{...priceCss(attributes)}}>
<RichText style={{fontSize: (attributes.priceFontSize / 2) + 'px'}}
className={'symbol'}
tagName="span" value={attributes.symbol}
onChange={(symbol) => setAttributes({symbol})}
placeholder={__('$')}/>
<RichText className={'amount'}
tagName="span" value={attributes.price}
onChange={(price) => setAttributes({price})}
placeholder={__('99.99')}/>
{attributes.recurring && <RichText
style={{fontSize: `${attributes.descrFontSize}${attributes.descrFontSizeUnit}`}}
tagName="span" value={attributes.recurringTime}
className="recurring"
onChange={(value) => setAttributes({recurringTime: value})}
placeholder={__('/month', 'attire-blocks')}/>}
</div>
{attributes.showFeatures && <RichText
style={{...listCss(attributes)}}
multiline="li"
tagName="ul"
className="features"
onChange={(nextValues) => setAttributes({features: nextValues})}
value={attributes.features}
placeholder={__('Write list…', 'attire-blocks')}
/>}
<InnerBlocks allowedBlocks={['attire-blocks/buttons']}
template={[['attire-blocks/buttons', {
buttonAlignment: 'center'
}]]}
templateLock="all"/>
</div>
</div>
</div>
</Fragment>
</Fragment>
);
},
save: ({attributes, className}) => {
//const {attributes} = props;
return (
<Fragment>
<style>
{listIconCss(attributes)}
</style>
<div className={"atbs atbs-pricing-table " + className}
id={'atbs-pricing-table-' + attributes.blockId}>
<div className="plan"
style={{...planCss(attributes)}}>
{attributes.title &&
<div className="head" style={{...titleCss(attributes)}}>
<RichText.Content style={{...titleTypographyCss(attributes)}} tagName="h2" className={'m-0'}
value={attributes.title}/>
</div>}
<div className='atbs_pricing_table_body'>
{attributes.description &&
<RichText.Content
style={{...descrCss(attributes)}}
className={'description'} tagName="p" value={attributes.description}/>}
<div className="price" style={{...priceCss(attributes)}}>
<RichText.Content style={{fontSize: (attributes.priceFontSize / 2) + 'px'}}
className={'symbol'} tagName="span" value={attributes.symbol}/>
<RichText.Content
style={{
color: attributes.bodyTextColor,
fontSize: (attributes.priceFontSize) + 'px'
}}
className={'amount'}
tagName="span" value={attributes.price}/>
{attributes.recurring && <RichText.Content
style={{fontSize: `${attributes.descrFontSize}${attributes.descrFontSizeUnit}`}}
className="recurring"
tagName="span" value={attributes.recurringTime}/>}
</div>
</div>
{attributes.showFeatures && <RichText.Content
style={{...listCss(attributes)}}
className={'features'}
tagName="ul" value={attributes.features}/>}
<InnerBlocks.Content/>
</div>
</div>
</Fragment>
);
}
});
Share
Improve this question
edited Jan 5, 2021 at 8:12
Sally CJ
40.1k2 gold badges28 silver badges49 bronze badges
asked Jan 5, 2021 at 6:24
Shafayat AlamShafayat Alam
1496 bronze badges
8
|
Show 3 more comments
2 Answers
Reset to default 1After about an hour of trial and error, I found that the outmost <Fragment>
was the culprit. But I still can't figure out why! Replacing it with <div>
fixed it.
So the code looks like this now:
edit: (props) => {
const {attributes, setAttributes} = props;
const headingBgOverlay = Util.getBgOverlay(attributes, 'heading');
const bodyBgOverlay = Util.getBgOverlay(attributes, 'body');
useEffect(() => {
setAttributes({blockId: Util.guidGenerator()});
}, []);
useEffect(() => {
console.log(props)
console.log(props.className)
console.log(attributes.className)
setAttributes({headingBgOverlay});
setAttributes({bodyBgOverlay});
}, [attributes]);
return (
<div>
<style>
{listIconCss(attributes)}
</style>
<div className={"atbs atbs-pricing-table " + props.className}
id={'atbs-pricing-table-' + attributes.blockId}>
<div className="plan"
style={{...planCss(attributes)}}>
<div className="head" style={{...titleCss(attributes)}}>
<RichText style={{...titleTypographyCss(attributes)}} tagName="h2" className={'m-0'}
value={attributes.title}
onChange={(title) => setAttributes({title})}
placeholder={__('Plan name', 'attire-blocks')}/>
</div>
<div className='atbs_pricing_table_body'>
<RichText
style={{...descrCss(attributes)}}
className={'description'} tagName="p" value={attributes.description}
onChange={(description) => setAttributes({description})}
placeholder={__('Description...', 'attire-blocks')}/>
<div className="price" style={{...priceCss(attributes)}}>
<RichText style={{fontSize: (attributes.priceFontSize / 2) + 'px'}}
className={'symbol'}
tagName="span" value={attributes.symbol}
onChange={(symbol) => setAttributes({symbol})}
placeholder={__('$')}/>
<RichText className={'amount'}
tagName="span" value={attributes.price}
onChange={(price) => setAttributes({price})}
placeholder={__('99.99')}/>
{attributes.recurring && <RichText
style={{fontSize: `${attributes.descrFontSize}${attributes.descrFontSizeUnit}`}}
tagName="span" value={attributes.recurringTime}
className="recurring"
onChange={(value) => setAttributes({recurringTime: value})}
placeholder={__('/month', 'attire-blocks')}/>}
</div>
{attributes.showFeatures && <RichText
style={{...listCss(attributes)}}
multiline="li"
tagName="ul"
className="features"
onChange={(nextValues) => setAttributes({features: nextValues})}
value={attributes.features}
placeholder={__('Write list…', 'attire-blocks')}
/>}
<InnerBlocks allowedBlocks={['attire-blocks/buttons']}
template={[['attire-blocks/buttons', {
buttonAlignment: 'center'
}]]}
templateLock="all"/>
</div>
</div>
</div>
</div>
);
},
save: ({attributes, className}) => {
//const {attributes} = props;
return (
<div>
<style>
{listIconCss(attributes)}
</style>
<div className={"atbs atbs-pricing-table " + className}
id={'atbs-pricing-table-' + attributes.blockId}>
<div className="plan"
style={{...planCss(attributes)}}>
{attributes.title &&
<div className="head" style={{...titleCss(attributes)}}>
<RichText.Content style={{...titleTypographyCss(attributes)}} tagName="h2" className={'m-0'}
value={attributes.title}/>
</div>}
<div className='atbs_pricing_table_body'>
{attributes.description &&
<RichText.Content
style={{...descrCss(attributes)}}
className={'description'} tagName="p" value={attributes.description}/>}
<div className="price" style={{...priceCss(attributes)}}>
<RichText.Content style={{fontSize: (attributes.priceFontSize / 2) + 'px'}}
className={'symbol'} tagName="span" value={attributes.symbol}/>
<RichText.Content
style={{
color: attributes.bodyTextColor,
fontSize: (attributes.priceFontSize) + 'px'
}}
className={'amount'}
tagName="span" value={attributes.price}/>
{attributes.recurring && <RichText.Content
style={{fontSize: `${attributes.descrFontSize}${attributes.descrFontSizeUnit}`}}
className="recurring"
tagName="span" value={attributes.recurringTime}/>}
</div>
</div>
{attributes.showFeatures && <RichText.Content
style={{...listCss(attributes)}}
className={'features'}
tagName="ul" value={attributes.features}/>}
<InnerBlocks.Content/>
</div>
</div>
</div>
);
}
});
Looks like the outmost
<Fragment>
was the culprit. But I still can't figure out why! Replacing it with<div>
fixed it.
If you're on WordPress 5.6.0, you don't need to replace the <Fragment>
with <div>
. :)
And that's because WordPress 5.6.0 actually came with block API version 2 which introduced a new hook named useBlockProps
that should be used in a block's edit()
and save()
functions — you can read more on the link I provided, but basically, with useBlockProps
, you'd be able to use Fragment
as the outmost wrapper.
Working example based on the one here:
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { Fragment } from '@wordpress/element';
registerBlockType( 'my-plugin/foo-block', {
// Required; use the block API version 2
apiVersion: 2,
title: 'Foo Block',
category: 'design',
attributes: {
content: {
type: 'array',
source: 'children',
selector: 'p',
},
},
// In edit(), use useBlockProps()
edit: ( props ) => {
const { attributes: { content }, setAttributes, className } = props;
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } );
};
return (
<Fragment>
<div className={ blockProps.className }>
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
value={ content }
/>
<p>{ 'Back-end: ' + blockProps.className }</p>
</div>
</Fragment>
);
},
// In save(), use useBlockProps.save()
save: ( props ) => {
const blockProps = useBlockProps.save();
return (
<Fragment>
<div className={ blockProps.className }>
<RichText.Content
{ ...blockProps }
tagName="p"
value={ props.attributes.content }
/>
<p>{ 'Front-end: ' + blockProps.className }</p>
</div>
</Fragment>
);
},
} );
So as you can see above, to get the additional CSS class(es) ( and other/auto-generated CSS class(es) ), I used blockProps.className
and not props.className
which gave us undefined
.
useEffect()
? – Sally CJ Commented Jan 5, 2021 at 8:15console.log(props.className)
asundefined
. Commenting outuseEffects
has no effect on the issue. – Shafayat Alam Commented Jan 5, 2021 at 8:28CSSEditor
) and then see if there's any of them that's causing the issue. I.e. Try your block with the bare setup (basic code) and add the internal components one at a time. – Sally CJ Commented Jan 5, 2021 at 10:23<Fragment>
was the culprit. But I still can't figure out why! Replacing it with<div>
fixed it. – Shafayat Alam Commented Jan 5, 2021 at 14:14