Gutenberg, with all its awesomeness, provides a bunch of selector functions that returns value indicating various states in the Gutenberg’s editorial process. But often times, we need to perform a task – such as calling a function after the post has finished saving.
Under the core/editor
data store, it provides 2 selector methods – isSavingPost() and isAutosavingPost() which indicates when a post has begun saving or autosaving, but it does not indicate when the post has finished saving/updating/publishing ….or whatever you would like to call it.
So, how can we implement something awesome that will help us perform tasks after a post save?
For a thorough understanding, add this simple snippet in your functions.php
file:
add_action( 'save_post', function() {
sleep( 5 );
} );
Code language: JavaScript (javascript)
This snippet simulates some “long server-side process” and will help us confirm that our implementation actually works!
My initial plan was to share the code, but I think it would be a good idea to just create a hook that can be reused every time.
So… the hook
The name of our hook will be useAfterSave()
import { useBlockProps } from '@wordpress/block-editor';
import { useRef, useState, useEffect } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
/**
* Returns `true` if the post is done saving, `false` otherwise.
*
* @returns {Boolean}
*/
const useAfterSave = () => {
const [ isPostSaved, setIsPostSaved ] = useState( false );
const isPostSavingInProgress = useRef( false );
const { isSavingPost, isAutosavingPost } = useSelect( ( __select ) => {
return {
isSavingPost: __select( 'core/editor' ).isSavingPost(),
isAutosavingPost: __select( 'core/editor' ).isAutosavingPost(),
}
} );
useEffect( () => {
if ( ( isSavingPost || isAutosavingPost ) && ! isPostSavingInProgress.current ) {
setIsPostSaved( false );
isPostSavingInProgress.current = true;
}
if ( ! ( isSavingPost || isAutosavingPost ) && isPostSavingInProgress.current ) {
// Code to run after post is done saving.
setIsPostSaved( true );
isPostSavingInProgress.current = false;
}
}, [ isSavingPost, isAutosavingPost ] );
return isPostSaved;
};
/**
* The edit function of an example block.
*
* @return {WPElement} Element to render.
*/
export default function Edit() {
const isAfterSave = useAfterSave();
useEffect( () => {
if ( isAfterSave ) {
// Add your code here that must run after the post is saved.
console.log( '...done saving...' )
}
}, [ isAfterSave ] );
return (
<p { ...useBlockProps() }>
{ __( 'Todo List – hello from the editor!', 'todo-list' ) }
</p>
);
}
Code language: JavaScript (javascript)
Our hook in action
I did not want to use the subscribe()
method from @wordpress/data
just due to the number of times it is triggered. I think our implementation solves that problem!
Hope this helps!
Leave a Reply