尝试将编辑函数转换为能够使用Reaction生命周期方法的类

时间:2021-11-28 作者:Iogui

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?

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.

1 个回复
最合适的回答,由SO网友:Iogui 整理而成

事实证明,至少对于我的特定用例,没有必要使用类或与React生命周期方法交互。我的代码已经将组件作为函数使用,但由于某种原因,我当时无法看到它。我可能在测试时出错了。

但我做了一些研究发现React的人an argument against using class in javascript. 为了解决过去只能通过类完成的事情,他们创建了hooks functionality 供功能性React组件使用。如果需要与React状态交互,请查看新的state hook 在现代React应用程序中,一切似乎都正常运行。这将是我的下一步,因为即使React的人也建议不要在新的React组件上使用类。因此,现在我将用我在研究中发现的东西回答我自己的问题,以帮助真正需要这些东西的人:

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?

目前看来,似乎没有办法使用类,而且仍然具有useBlockProps功能,因为Wordpress的人似乎没有为类实现它,而React挂钩不适用于类。

Am I doing something wrong?

是的,我不需要使用类,也不需要直接与React生命周期方法交互,因为我的函数代码已经在工作了。

Is it not allowed anymore?

useBlockProps 是一个钩子,所以它可能只是针对功能组件创建的。因此,它不能与React Class组件一起使用,但React Class组件仍然可以使用。现在使用WordPress React类有点困难,因为WordPress的人似乎不支持它。

Is there a better alternative to be able to use the React lifecycle?

是的,现在似乎可以从具有useState 可以直接从@wordpress/element 打包源代码似乎只是importing it directly from React 无需修改。如果你有必要的话就去做,但一定要照顾好possible colateral effects.

相关推荐

迁移到新域名后出现JavaScript/AJAX错误

我已经将一个客户的站点从旧的垃圾域名迁移到新的域名,以更好地代表他们的业务。然而,自从移动以来,似乎出现了某种Javascript/Ajax问题。例如,我似乎无法切换选项卡(在ajax页面上),而;“快速编辑”;工具根本不起作用。当单击任何页面上的“快速编辑”链接时,我在F12控制台中发现此错误。Uncaught TypeError: Cannot read property \'hasClass\' of undefined at HTMLDocument.<anonymous&g