block editor – Can this react script be optimized? How to make it faster

Question

This is my first attempt to work with WordPress blocks and also my first time working with React.

The code below adds the possibility to conditionally show blocks.

My question is related to the “select pages” section, or the “useSelect”.

I show a list of pages which have been selected previously. I also show a list of pages based on a search. Whenever someone selects a page I want the checkbox to move from the search list to the selected list. I can do that by adding the ‘pagesArray’ as a dependency to useSelect. But that makes two REST api calls, which is slow. How can I move them without making the api calls again?

Right now the currently selected list only gets updated when a search is done.

Also, as this is my first React code, any feedback is welcome!

This is my code:

const { __ }                            = wp.i18n;
const { createHigherOrderComponent }    = wp.compose;
const { Fragment }                      = wp.element;
const { InspectorControls }             = wp.blockEditor;
const { PanelBody, ToggleControl, CheckboxControl }      = wp.components;
import { SearchControl, Spinner } from 'wordpress user/components';
import {useState } from "wordpress user/element";
import { useSelect } from 'wordpress user/data';
import { store as coreDataStore } from 'wordpress user/core-data';
import { decodeEntities } from 'wordpress user/html-entities';  

// Add attributes
function addFilterAttribute(settings) {
    if (typeof settings.attributes !== 'undefined') {
        settings.attributes = Object.assign(settings.attributes, {
            hideOnMobile: {
                type: 'boolean',
            },
            onlyOnHomePage: {
                type: 'boolean',
            },
            onlyLoggedIn: {
                type: 'boolean',
            },
            onlyOn: {
                type: 'object'
            }
        });
    }
    return settings;
}
 
wp.hooks.addFilter(
    'blocks.registerBlockType',
    'sim/block-filter-attribute',
    addFilterAttribute
);

// Add controls to panel
const blockFilterControls = createHigherOrderComponent((BlockEdit) => {
    return ( props ) => {

        const { attributes, setAttributes } = props;

        const [ searchTerm, setSearchTerm ] = useState( '' );

        let pageIds = [];
        if(attributes.onlyOn != undefined){
            pageIds = Object.keys(attributes.onlyOn);
        }

        let checkedPages    = {};
        
        for (const id in attributes.onlyOn) {
            checkedPageshttps://wordpress.stackexchange.com/q/408335 = true;
        }

        const [ pagesArray, setPages ] = useState( checkedPages);

        const PagesList = function ( { hasResolved, pages, showLoader = true } ) {
            if ( ! hasResolved ) {
                return(
                    <>
                    <Spinner />
                    <br></br>
                    </>
                );
            }
        
            if(attributes.onlyOn == undefined){
                attributes.onlyOn = {};
            }
        
            if ( ! pages?.length ) {
                if(showLoader){
                    return <div> {__('No search results', 'sim')}</div>;
                }

                return '';
            }
        
            const onPagesChanged    = function(checked){
                let copy = Object.assign({}, pagesArray);
                // this is the page id
                copy[this]  = checked;
        
                setAttributes({onlyOn: copy});
        
                setPages(copy);
            }
        
            return (
                pages?.map( ( page ) => {
        
                    return (<CheckboxControl
                        label       = {decodeEntities( page.title.rendered )}
                        onChange    = {onPagesChanged.bind(page.id)}
                        checked     = {pagesArray[page.id]}
                    />)
                } )
            );
        }

        const { pages, selectedPages, pagesResolved,  selectedPagesResolved} = useSelect(
            ( select) => {
                // find all pages excluding the already selected pages
                const query = {exclude : pageIds};
                if ( searchTerm ) {
                    query.search = searchTerm;
                }
                const pagesArgs         = [ 'postType', 'page', query ];

                // Find all selected pages
                const selectedPagesArgs = [ 'postType', 'page', {include : pageIds} ];

                return {
                    pages: select( coreDataStore ).getEntityRecords(
                        ...pagesArgs
                    ),
                    selectedPages: select( coreDataStore ).getEntityRecords(
                        ...selectedPagesArgs
                    ),
                    pagesResolved: select( coreDataStore ).hasFinishedResolution(
                        'getEntityRecords',
                        pagesArgs
                    ),
                    selectedPagesResolved: select( coreDataStore ).hasFinishedResolution(
                        'getEntityRecords',
                        selectedPagesArgs
                    )
                };
            },
            [ searchTerm ]
        );

        let selectedPagesControls="";
        if(pageIds.length > 0){
            selectedPagesControls    =   <>
                <i> {__('Currently selected pages', 'sim')}:</i>
                <br></br>
                <PagesList hasResolved={ selectedPagesResolved } pages={selectedPages} props={ props } showLoader={false}/>
            </>;
        }

        return (
            <Fragment>
                <BlockEdit { ...props } />
                <InspectorControls>
                    <PanelBody title={ __( 'Block Visibility' ) }>
                        <ToggleControl
                            label={__('Hide on mobile', 'sim')}
                            checked={!!attributes.hideOnMobile}
                            onChange={(newval) => setAttributes({ hideOnMobile: !attributes.hideOnMobile })}
                        />

                        <ToggleControl
                            label={__('Only on home page', 'sim')}
                            checked={!!attributes.onlyOnHomePage}
                            onChange={(newval) => setAttributes({ onlyOnHomePage: !attributes.onlyOnHomePage })}
                        />

                        <ToggleControl
                            label={__('Hide if not logged in', 'sim')}
                            checked={!!attributes.onlyLoggedIn}
                            onChange={(newval) => setAttributes({ onlyLoggedIn: !attributes.onlyLoggedIn })}
                        />
                    
                        <strong>{__('Select pages', 'sim')}</strong><br></br>
                        {__('Select pages you want this widget to show on', 'sim')}.<br></br>
                        {__('Leave empty for all pages', 'sim')}<br></br>
                        <br></br>
                        {selectedPagesControls}
                        <i>{__('Use searchbox below to search for more pages to include', 'sim')}</i>
                        <SearchControl onChange={ setSearchTerm } value={ searchTerm } />
                        <PagesList hasResolved={ pagesResolved } pages={ pages } props={ props }/>
                    </PanelBody>
                </InspectorControls>
            </Fragment>
        );
    };
}, 'blockFilterControls');
 
wp.hooks.addFilter(
    'editor.BlockEdit',
    'sim/block-filter-controls',
    blockFilterControls
);

0
user2190196 2 weeks 2022-08-06T02:03:52-05:00 0 Answers 0 views 0

Leave an answer

Browse
Browse