Skip to main content
added 1812 characters in body
Source Link
Iogui
  • 141
  • 6

EDIT: The rendering component state problem

The question above arouse from my research to solve a component state problem I have found. @TomJNowell stated that the problem I have is not related to state, so I'm posting a simplification of my code to only address the original problem that led me to research about dealing with state on WordPress block components.

edit.js:

export default function Edit({attributes, setAttributes}) {
    const getClassName = (status) => status === 'info'? 'mbp-black' : 'mbp-red';
    const getSelectedIcon = (status) => status == 'info' ? icons.info : icons.error;

    return (
        <div{...useBlockProps({className: getClassName(attributes.status) })}>
            <BlockControls>
                <ToolbarDropdownMenu hasArrowIndicator
                                     icon={ getSelectedIcon(attributes.status) }
                                     label="Status"
                                     controls={[
                                         {
                                             icon: icons.info,
                                             title: 'Info',
                                             onClick: () => setAttributes({status: 'info'}),
                                             isActive: attributes.status === 'info'
                                         },
                                         {
                                             icon: icons.error,
                                             title: 'Error',
                                             onClick: () => setAttributes({status: 'error'}),
                                             isActive: attributes.status === 'error'
                                         }
                                     ]}
                />
            </BlockControls>
            <p >
                {__(
                    'I have state!!!!',
                    'multiple-blocks-plugin'
                )}
            </p>
        </div>

    );

What I want to achieve with this code is, that immediately after the user chooses Info or Error on the dropdown menu, the component on the editor be re-rendered with the equivalent css class and also if I've selected the Error option, the next time I open the menu, this should be the selected option on the menu.

EDIT: The rendering component state problem

The question above arouse from my research to solve a component state problem I have found. @TomJNowell stated that the problem I have is not related to state, so I'm posting a simplification of my code to only address the original problem that led me to research about dealing with state on WordPress block components.

edit.js:

export default function Edit({attributes, setAttributes}) {
    const getClassName = (status) => status === 'info'? 'mbp-black' : 'mbp-red';
    const getSelectedIcon = (status) => status == 'info' ? icons.info : icons.error;

    return (
        <div{...useBlockProps({className: getClassName(attributes.status) })}>
            <BlockControls>
                <ToolbarDropdownMenu hasArrowIndicator
                                     icon={ getSelectedIcon(attributes.status) }
                                     label="Status"
                                     controls={[
                                         {
                                             icon: icons.info,
                                             title: 'Info',
                                             onClick: () => setAttributes({status: 'info'}),
                                             isActive: attributes.status === 'info'
                                         },
                                         {
                                             icon: icons.error,
                                             title: 'Error',
                                             onClick: () => setAttributes({status: 'error'}),
                                             isActive: attributes.status === 'error'
                                         }
                                     ]}
                />
            </BlockControls>
            <p >
                {__(
                    'I have state!!!!',
                    'multiple-blocks-plugin'
                )}
            </p>
        </div>

    );

What I want to achieve with this code is, that immediately after the user chooses Info or Error on the dropdown menu, the component on the editor be re-rendered with the equivalent css class and also if I've selected the Error option, the next time I open the menu, this should be the selected option on the menu.

Source Link
Iogui
  • 141
  • 6

Trying to turn the Edit function into a class to be able to use React lifecycle methods

In order to be able to use React lifecycle methods I'm trying to change the default Edit function created by @wordpress/create-block into a javascript class like in this simple test example:

import { registerBlockType } from '@wordpress/blocks';

/**
 * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
 * All files containing `style` keyword are bundled together. The code used
 * gets applied both to the front of your site and to the editor.
 *
 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
 */
import './style.scss';

/**
 * Internal dependencies
 */
//import Edit from './edit';
import save from './save';
import icons from "../../icons";
import {Component} from "@wordpress/element";
import {useBlockProps} from "@wordpress/block-editor";

export default class TestClass extends Component {
    render() {

        return (
            <div {...useBlockProps()}>
                This is only a test!!
            </div>
        );
    }

}

/**
 * Every block starts by registering a new block type definition.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
 */
registerBlockType('multiple-blocks-plugin/notice', {
    icon: icons.note,

    /**
     * @see ./edit.js
     */
    edit: TestClass, //Edit,

    /**
     * @see ./save.js
     */
    save,
});

That's an approach I've seen in some tutorials like this one but, for some reason, I'm not been able to do it. The above code, gives me the following error at the browser console:

react_devtools_backend.js:2540 Error: Minified React error #321; visit https://reactjs.org/docs/error-decoder.html?invariant=321 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
    at Object.S (react-dom.min.js?ver=16.13.1:84)
    at d.useContext (react.min.js?ver=16.13.1:31)
    at xu (block-editor.min.js?ver=fc8c27c6e95e7e0d59b4e344cb9ddfed:12)
    at TestClass.render (index.js:30)
    at Ie (react-dom.min.js?ver=16.13.1:104)
    at rh (react-dom.min.js?ver=16.13.1:103)
    at zj (react-dom.min.js?ver=16.13.1:228)
    at Th (react-dom.min.js?ver=16.13.1:152)
    at tj (react-dom.min.js?ver=16.13.1:152)
    at Te (react-dom.min.js?ver=16.13.1:146)

Digging for a solution, I've found out that the problem is caused by the function useBlockProps. Is there a way to avoid it without loosing the useBlockProps provided functionalities?

So now I have the following questions (all related to the problem explained above):

  • Am I doing something wrong? I don't see in the WordPress docs an advice to not use the useBlockProps function when working with classes but I am new to Wordpress development so I'm not sure.
  • Is it not allowed anymore?
  • Is there a better alternative to be able to use the React lifecycle?