You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Issue 1: Cannot load a component during save mode that has hooks.
Issue 2: Components are loaded as static HTML on the front end rather than React components.
Idea:
It would be fantastic if there was a switch available in the block.json that told WordPress to load a 'view' component as a React component on the front-end. That would mean there would be an edit, save, and view version of the component registered during block registration. Better yet, if there was an optional 'view' version of the component provided during registration it would automatically load it as React otherwise use the save version which would be static. The save version would be markup only per the example below and the edit and view versions would have hook state management, etc.
Idea two:
Automatically replace the hook values with null values during save mode in order to get static markup (this would allow 3rd party components to be used as is) and use switch in block.json to load the 'save' component as fully React component on the front-end.
I solved issue 1 above by separating out the markup from the state management as two components as indicated below and I resolved issue 2 by parsing the static HTML to get user provided values and loading the React component. These issues make it very difficult to use 3rd party components or our own React Component libraries unless we customize them for WordPress. Who has time for that! ;)
Custom component:
import { useState } from 'react';
/**
*
* @param {Component} [props.children] - Required - Inner content of accordion. Content can be HTML.
* @param {string or component} [props.title] - Required - Link text.
* @param {string} [props.className] Class name to add to outer wrapper for customization.
*
* As of 11/22 WordPress does not allow hook calls during the save block mode therefore separate out the
* markup from the interactive portion of the function so that Save can load markup only.
*
* Component classes work without creating separation between parent with state management and child markup only comp
* however using function classes and hooks is considered the modern standard and uses
* much leaner syntax. Interactivity is reloaded on the front-end through the viewScript.
* - ESat
*/
const Accordion = (props) => {
const {
className = false,
title = '',
children,
valuesAreHtml = false
} = props;
const [showBody, setShowBody] = useState(false);
const toggleContentDisplay = () => {
setShowBody(!showBody);
};
return (
<AccordionMarkup
className={className}
title={title}
valuesAreHtml={valuesAreHtml}
showBody={showBody}
toggleContentDisplay={toggleContentDisplay}
>
{children}
</AccordionMarkup>
)
}
export const AccordionMarkup = (props) => {
const {
className = false,
title = '',
children = '',
toggleContentDisplay = false,
showBody = false,
valuesAreHtml = false
} = props;
return (
<section className={`accordion${className ? ' ' + className : ''}`}>
<dl>
<button onMouseDown={toggleContentDisplay} className="accordion__title" aria-expanded="false">
{valuesAreHtml &&
<dt dangerouslySetInnerHTML={{ __html: title }} />
}
{!valuesAreHtml &&
<dt>{title}</dt>
}
</button>
{valuesAreHtml &&
<dd className="accordion__content" style={{ display: `${showBody ? 'block' : 'none'}` }}
dangerouslySetInnerHTML={{ __html: children }}
>
</dd>
}
{!valuesAreHtml &&
<dd className="accordion__content" style={{ display: `${showBody ? 'block' : 'none'}` }}>
{children}
</dd>
}
</dl>
</section>
);
}
export default Accordion;
viewScript:
/**
* !! IMPORTANT !!
* viewScript is being used to reload block React elements on the front-end because save.js stripes
* the component hooks and standard state values thereby nullifying interactivity based on state. - ESat
*
* An alternative to loading the React component here is to use the JavaScript that comes with the HTML
* WCL here. That would mean that the WP plug-in would use React on the back-end and static HTML on the
* front-end as is done now. While using the WCL React library is still better than embedding the HTML
* directly in WordPress blocks using static JS on the front-end is not ideal. - ESat
*
*/
import { render } from '@wordpress/element'
import Accordion from './Accordion.function'
document.querySelectorAll('[data-accordionroot').forEach((acc) => {
const className = acc.children[0].classList; /* okay if accordion class on twice */
const title = acc.querySelector('.accordion__title dt :first-child');
const content = acc.querySelector('.accordion__content :first-child');
render(<Accordion className={className} title={title.outerHTML} valuesAreHtml={true}>{content.outerHTML}</Accordion>, acc);
});
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Issue 1: Cannot load a component during save mode that has hooks.
Issue 2: Components are loaded as static HTML on the front end rather than React components.
Idea:
It would be fantastic if there was a switch available in the block.json that told WordPress to load a 'view' component as a React component on the front-end. That would mean there would be an edit, save, and view version of the component registered during block registration. Better yet, if there was an optional 'view' version of the component provided during registration it would automatically load it as React otherwise use the save version which would be static. The save version would be markup only per the example below and the edit and view versions would have hook state management, etc.
Idea two:
Automatically replace the hook values with null values during save mode in order to get static markup (this would allow 3rd party components to be used as is) and use switch in block.json to load the 'save' component as fully React component on the front-end.
I solved issue 1 above by separating out the markup from the state management as two components as indicated below and I resolved issue 2 by parsing the static HTML to get user provided values and loading the React component. These issues make it very difficult to use 3rd party components or our own React Component libraries unless we customize them for WordPress. Who has time for that! ;)
Custom component:
viewScript:
Beta Was this translation helpful? Give feedback.
All reactions