I'm not very familiar with React and Redux. I have a problem with Gutenberg to get the value of the withState variable within the save function. Here's my code:
edit( {attributes, setAttributes, className} ) {
var link_text = attributes.link_text;
var link_url = attributes.link_url;
var svg_url = attributes.svg_url;
var template_url = ww_blocks.templateUrl;
var hasExternalURL = attributes.hasExternalURL;
function onChangeLinkText ( content ) {
setAttributes({link_text: content})
}
function onChangeLinkURL ( content ) {
setAttributes({link_url: content})
}
setAttributes({svg_url: template_url + '/img/icons.svg#button-next'});
const LinkToggleControl = withState( {
hasExternalURL: false,
} )( ( { hasExternalURL, setState } ) => (
<ToggleControl
label="Externer Link"
help={ hasExternalURL ? 'Es ist ein externer Link.' : 'Kein externer Link.' }
checked={ hasExternalURL }
onChange={ () => setState( ( state ) => ( { hasExternalURL: ! state.hasExternalURL } ) ) }
/>
) );
return ([
<InspectorControls>
<PanelBody title="Link Parameter">
<div id="ww-container-inspector-control-wrapper">
<label class="blocks-base-control__label" for="mce_1">Link Text</label>
<TextControl
onChange={onChangeLinkText} // onChange event callback
value={link_text} // Input Binding
/>
<label class="blocks-base-control__label" for="mce_2">Link URL</label>
<TextControl
onChange={onChangeLinkURL} // onChange event callback
value={link_url} // Input Binding
/>
<LinkToggleControl />
</div>
</PanelBody>
</InspectorControls>,
<div className={ className }>
<a class="btn btn-std" href="#">
<svg role="img" class="symbol" aria-hidden="true" focusable="false">
<use href={svg_url}></use>
</svg>
<span>{link_text}</span>
</a>
</div>
]);
},
save( { attributes } ) {
return (
<a className="btn btn-std" href={attributes.link_url} target={ attributes.hasExternalURL ? '_blank' : '' } title={ attributes.hasExternalURL ? 'Seite öffnet in neuem Fenster' : '' }>
<svg role="img" class="symbol" aria-hidden="true" focusable="false">
<use href={attributes.svg_url}></use>
</svg>
<span>{attributes.link_text}</span>
</a>
);
},
} );
I'm not very familiar with React and Redux. I have a problem with Gutenberg to get the value of the withState variable within the save function. Here's my code:
edit( {attributes, setAttributes, className} ) {
var link_text = attributes.link_text;
var link_url = attributes.link_url;
var svg_url = attributes.svg_url;
var template_url = ww_blocks.templateUrl;
var hasExternalURL = attributes.hasExternalURL;
function onChangeLinkText ( content ) {
setAttributes({link_text: content})
}
function onChangeLinkURL ( content ) {
setAttributes({link_url: content})
}
setAttributes({svg_url: template_url + '/img/icons.svg#button-next'});
const LinkToggleControl = withState( {
hasExternalURL: false,
} )( ( { hasExternalURL, setState } ) => (
<ToggleControl
label="Externer Link"
help={ hasExternalURL ? 'Es ist ein externer Link.' : 'Kein externer Link.' }
checked={ hasExternalURL }
onChange={ () => setState( ( state ) => ( { hasExternalURL: ! state.hasExternalURL } ) ) }
/>
) );
return ([
<InspectorControls>
<PanelBody title="Link Parameter">
<div id="ww-container-inspector-control-wrapper">
<label class="blocks-base-control__label" for="mce_1">Link Text</label>
<TextControl
onChange={onChangeLinkText} // onChange event callback
value={link_text} // Input Binding
/>
<label class="blocks-base-control__label" for="mce_2">Link URL</label>
<TextControl
onChange={onChangeLinkURL} // onChange event callback
value={link_url} // Input Binding
/>
<LinkToggleControl />
</div>
</PanelBody>
</InspectorControls>,
<div className={ className }>
<a class="btn btn-std" href="#">
<svg role="img" class="symbol" aria-hidden="true" focusable="false">
<use href={svg_url}></use>
</svg>
<span>{link_text}</span>
</a>
</div>
]);
},
save( { attributes } ) {
return (
<a className="btn btn-std" href={attributes.link_url} target={ attributes.hasExternalURL ? '_blank' : '' } title={ attributes.hasExternalURL ? 'Seite öffnet in neuem Fenster' : '' }>
<svg role="img" class="symbol" aria-hidden="true" focusable="false">
<use href={attributes.svg_url}></use>
</svg>
<span>{attributes.link_text}</span>
</a>
);
},
} );
Share
Improve this question
edited Jul 7, 2020 at 9:15
Tom J Nowell♦
61k7 gold badges79 silver badges148 bronze badges
asked Jul 7, 2020 at 9:06
jsjqueryreactjsjqueryreact
535 bronze badges
1
|
1 Answer
Reset to default 2That is not how blocks work. If you want to save something, it must be a block attribute.
withState
lets a function have internal state, so it's useful if you want to add toggle controls to your blocks UI, but it should not be used to store things that need to be saved. So you might use it to help build the UI for a block, hold temporary things, anything that doesn't need to be solved and can be eliminated. E.g. wether a panel is open or collapsed.
Further, if we ignore this, and try to use withState
we run into several issues:
- the state in the save function would not be the same state, so the value wouldn't carry over
- the information would be in the HTML, but because it isn't a block attribute it would not be saved and the next time you opened the editor it would dissapear and need to be reset or the HTML would change
withState
is meant to be used inside a React component, but thesave
method is intended for generating the final HTML to go in the database.
The fundamental problem here is that the LinkToggleControl
is using local ephemeral state to store wether it's toggled or not, when it should be using setAttributes
instead.
withState
isn't a variable it's a function call – Tom J Nowell ♦ Commented Jul 7, 2020 at 9:19