Search code examples
wordpressreactjswordpress-gutenberg

Saving SelectControl option


I have managed to create a WordPress custom Gutenberg block and I've created a panel section to store all my blocks options.

However, I am very new to react and I've managed to scaffold this together. I'm trying to give this select an initial state and also save the state when changed.

I know I need to do something with withState but I'm not sure I can see my promise is failing is that but I'm not sure why.

// Block Options
const withInspectorControls =  createHigherOrderComponent( ( BlockEdit ) => {
  return (props) => {
    const size = {size:"display-2"};
    return (
      <Fragment>
        <BlockEdit { ...props } />
        <InspectorControls>
          <PanelBody title="Display Block Settings"
            icon="welcome-widgets-menus"
            initialOpen={ true }
          >
            <SelectControl
              label="Display Size"
              value={size}
              options={[
                { label: 'Display 1', value: 'display-1' },
                { label: 'Display 2', value: 'display-2' },
                { label: 'Display 3', value: 'display-3' },
                { label: 'Display 4', value: 'display-4' },
              ]}
              onChange={ ( size ) => { setState( { size:size } ) } } 
            />
          </PanelBody>
        </InspectorControls>
      </Fragment>
    );
  };
}, "withInspectorControl" );

wp.hooks.addFilter( 'editor.BlockEdit', 'display-heading/with-inspector-controls', withInspectorControls );

Solution

  • You're on the right track. As you already mentioned you really just need to add the withState HOC. This could look like this:

    // 1. add the withState import
    import { withState } from '@wordpress/compose';
    
    // 2. wrap your SelectControl with the withState HOC
    const MySelectControl = withState( {
        // this is your state, in this case display-2 would be the default
        size: 'display-2',
    } )( ( { size, setState } ) => (
        <SelectControl
            label="Size"
            value={ size }
            options={ [
                { label: 'Display 1', value: 'display-1' },
                { label: 'Display 2', value: 'display-2' },
                { label: 'Display 3', value: 'display-3' },
                { label: 'Display 4', value: 'display-4' },
            ] }
            onChange={ ( size ) => { setState( { size } ) } }
        />
    ) );
    
    // Block Options
    const withInspectorControls =  createHigherOrderComponent( ( BlockEdit ) => {
      return (props) => {
        return (
          <Fragment>
            <BlockEdit { ...props } />
            <InspectorControls>
              <PanelBody title="Display Block Settings"
                icon="welcome-widgets-menus"
                initialOpen={ true }
              >
                // 3. now you can add your component in your panel
                <MySelectControl />
              </PanelBody>
            </InspectorControls>
          </Fragment>
        );
      };
    }, "withInspectorControl" );
    
    wp.hooks.addFilter( 'editor.BlockEdit', 'display-heading/with-inspector-controls', withInspectorControls );
    

    Reacts Higher-Order Components can be really confusing in the beginning. But if you are familiar with the OOP paradigm, you can think of them like the composition pattern. The most important thing to know for Gutenberg development is the fact that they always return a new component. That's why I was able to use it like this <MySelectControl />.