Skip to content

Instantly share code, notes, and snippets.

@vfontjr
Created July 22, 2025 01:22
Show Gist options
  • Save vfontjr/4e94ad66524d1b1de8dcd1f0e1d38892 to your computer and use it in GitHub Desktop.
Save vfontjr/4e94ad66524d1b1de8dcd1f0e1d38892 to your computer and use it in GitHub Desktop.
import { dispatch } from '@wordpress/data';
const saveCustomData = (data) => {
return ( { select, dispatch } ) => {
const store = dispatch('my-plugin/store');
store.setSaving(true);
fetch('/wp-json/my-plugin/v1/save', {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
})
.then((res) => res.json())
.then((response) => store.setSaving(false));
};
};
// Dispatch the thunk
dispatch('my-plugin/store').saveCustomDataThunk();
import { dispatch } from '@wordpress/data';
dispatch('core').fetchEntityRecords( 'postType', 'post', { per_page: 5 } );
/* Enqueue this via enqueue_block_editor_assets */
import { registerPlugin } from '@wordpress/plugins';
import { PluginSidebar } from '@wordpress/edit-post';
import { TextControl, Button, PanelBody, Spinner } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { createReduxStore, register } from '@wordpress/data';
const STORE_NAME = 'thunk-demo/store';
const thunkDemoStore = createReduxStore(STORE_NAME, {
reducer(state = { saving: false }, action) {
switch (action.type) {
case 'SET_SAVING':
return { ...state, saving: action.payload };
default:
return state;
}
},
actions: {
setSaving(value) {
return { type: 'SET_SAVING', payload: value };
},
saveNoteThunk(note) {
return async ({ dispatch }) => {
dispatch.setSaving(true);
await fetch('/wp-json/thunk-demo/v1/save', {
method: 'POST',
body: JSON.stringify({ note }),
headers: { 'Content-Type': 'application/json' },
});
dispatch.setSaving(false);
};
},
},
selectors: {
isSaving(state) {
return state.saving;
},
},
});
register(thunkDemoStore);
const ThunkPanel = () => {
const [note, setNote] = useState('');
const { saveNoteThunk } = wp.data.dispatch(STORE_NAME);
const isSaving = wp.data.select(STORE_NAME).isSaving();
return (
<PluginSidebar name="thunk-panel" title="Thunk Panel">
<PanelBody>
<TextControl
label="Note"
value={note}
onChange={(val) => setNote(val)}
/>
<Button
isPrimary
isBusy={isSaving}
onClick={() => saveNoteThunk(note)}
>
{isSaving ? <Spinner /> : 'Save'}
</Button>
</PanelBody>
</PluginSidebar>
);
};
registerPlugin('thunk-panel', { render: ThunkPanel });
<?php
/**
* Plugin Name: Gutenberg Thunk Demo
* Description: Demonstrates use of thunks in a custom sidebar panel.
* Version: 1.0
* Author: Your Name
*/
add_action('init', function () {
register_rest_route('thunk-demo/v1', '/save', [
'methods' => 'POST',
'callback' => function ($request) {
$note = sanitize_text_field($request->get_param('note'));
// Save the note or do something with it.
return rest_ensure_response(['success' => true, 'note' => $note]);
},
'permission_callback' => '__return_true',
]);
});
// Immediate execution
const result = expensiveCall();
// Thunk pattern
const thunk = () => expensiveCall();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment