$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>plugins - Getting a custom Gutenberg component's state from outside that component|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

plugins - Getting a custom Gutenberg component's state from outside that component

matteradmin10PV0评论

I've registered a sidebar component in the block editor. I'd like to access the state of the component (MyPlugin) from outside of that component, in some arbitrary JavaScript in the same file. Is it possible to access the state via e.g. the wp object?

Or, is it possible, and would it be better to do this using props?

class MyPlugin extends Component {
    constructor() {
        super( ...arguments );

        // initial state
        this.state = {
            key: 'my_key',
            value: ''
        }
    }

    render() {
        return el(
            PluginPostStatusInfo,
            {
                className: 'my-panel-class'
            },
            el(
                TextControl,
                {
                    name: 'my_text_control_name',
                    label: __( 'My label', 'my-text-domain' ),
                    value: this.state.value,
                    onChange: ( value ) => {
                        this.setState( {
                            value
                        })
                    }
                }
            )
        );
    }
}

registerPlugin( 'my-plugin', {
    render: MyPlugin
} );

const myFunction = () => {
    // this function is hooked into an action elsewhere,
    // and needs to access the state of MyPlugin
}

What I'd ultimately like to do is access the textbox's value from a separate function. I don't mind how this is achieved, e.g. with state or props or some other means. I guess another approach would be to have the component write its value into a global variable when it changes, but that seems a bit clunky.

I've registered a sidebar component in the block editor. I'd like to access the state of the component (MyPlugin) from outside of that component, in some arbitrary JavaScript in the same file. Is it possible to access the state via e.g. the wp object?

Or, is it possible, and would it be better to do this using props?

class MyPlugin extends Component {
    constructor() {
        super( ...arguments );

        // initial state
        this.state = {
            key: 'my_key',
            value: ''
        }
    }

    render() {
        return el(
            PluginPostStatusInfo,
            {
                className: 'my-panel-class'
            },
            el(
                TextControl,
                {
                    name: 'my_text_control_name',
                    label: __( 'My label', 'my-text-domain' ),
                    value: this.state.value,
                    onChange: ( value ) => {
                        this.setState( {
                            value
                        })
                    }
                }
            )
        );
    }
}

registerPlugin( 'my-plugin', {
    render: MyPlugin
} );

const myFunction = () => {
    // this function is hooked into an action elsewhere,
    // and needs to access the state of MyPlugin
}

What I'd ultimately like to do is access the textbox's value from a separate function. I don't mind how this is achieved, e.g. with state or props or some other means. I guess another approach would be to have the component write its value into a global variable when it changes, but that seems a bit clunky.

Share Improve this question edited Jan 8, 2019 at 10:51 Sean asked Jan 8, 2019 at 10:45 SeanSean 6777 silver badges17 bronze badges 3
  • i guess not. the state is local. maybe InnerBlocks are the right for your requirements: github/WordPress/gutenberg/tree/master/packages/editor/src/… so you could nest two blocks.. – André Kelling Commented Jan 8, 2019 at 10:50
  • @AndréKelling, I've edited the question to say I'm happy to achieve this in any other way that's possible, so if the state is not available, perhaps props can be used. – Sean Commented Jan 8, 2019 at 10:52
  • if you need that value inside the react components or subcomponents state and props are the way to go. but if you need that data in an independent custom JS script your solution looks very good! – André Kelling Commented Jan 8, 2019 at 11:53
Add a comment  | 

2 Answers 2

Reset to default 5

To do so you need to use a redux store. To register your own you can follow the steps in the documentation. Here is the minimum that should achieve what you are looking for.

First, lets give the "shape" of the store in the initial state object:

const initial_state = {
    my_control: {
        value: ""
    },
};

Lets create a reducer that manipulates the state:

const reducer = (state = initial_state, action) => {
    switch (action.type) {
        case "UPDATE_MY_CONTROL_VALUE": {
            return {
                ...state,
                my_control: {
                    ...state.my_control,
                    value: action.value
                }
            };
        }
    }

    return state;
};

As you can see, we set the initial_state object we just created as the default value of the state.

Now lets add an action which updates the store, sending data to the reducer:

const actions = {
    updateMyControlValue(value) {
        return {
            type: "UPDATE_MY_CONTROL_VALUE",
            value
        };
    },
}

Lets add a selector that gets the data from the store:

const selectors = {
    getMyControlValue(state) {
        return state.my_control.value;
    },
};

And now we will register the store with the previous constants:

const { registerStore } = wp.data;

registerStore("my_plugin/my_store", {
    reducer,
    actions,
    selectors
});

Now the store is registered. We will connect the component to the store to get the latest value of my_control and to update it:

const { Component } = wp.element;
const { TextControl } = wpponents;
const { compose } = wppose;
const { withDispatch, withSelect } = wp.data;

class Text extends Component {
    render() {
        const { value, updateMyControlValue } = this.props;

        return (
            <TextControl
                value={value}
                onChange={updateMyControlValue}
            />
        );
    }
}

export default compose([
    withDispatch((dispatch, props) => {
        // This function here is the action we created before.
        const { updateMyControlValue } = dispatch("my_plugin/my_store");

        return {
            updateMyControlValue
        };
    }),
    withSelect((select, props) => {
        // This function here is the selector we created before.
        const { getMyControlValue } = select("my_plugin/my_store");

        return {
            value: getMyControlValue()
        };
    }),
])(Text);

This is a simple example, but you can take a look at the link on the documentation to see how you can use other functionality to enhance the store (for example, with controls and resolvers).

Also you can make use the core stores and their selectors and actions inside your component's withSelect and withDispatch.

I found a solution, but I'm not sure it's really the intended way to do this. I use the core editor datastore to set the value, then retrieve it from there in my function.

In the onChange callback in MyPlugin, in addition to setting the state I also save the value:

onChange: ( value ) => {
    this.setState( {
        value
    })

    // set data in store
    wp.data.select('core/editor').my_custom_key = value;
}

then in my function I just grab it out:

const myFunction = () => {
    var myData = wp.data.select('core/editor').my_custom_key;

    // do stuff with myData...
}
Post a comment

comment list (0)

  1. No comments so far