Andrea Gandino

Better undo/redo in the Block Editor

A quick & easy technique to group data-altering actions in the Block Editor.

WordPress

If you use WordPress and the Block Editor regularly to create your content, you may have noticed that the undo/redo functionality can get somewhat quirky, at times.

As a developer, I wanted to know why that happens, and the answer was fairly simple: every time there's a modification to a block's data, a new entry in the edit history is added by the Block Editor.

The intention behind this behavior is, of course, to allow users to go back and forth between changes.

The problem is that in complex blocks, especially in ones where there's shared functionality between a parent block and its children, sometimes you not only need to update the parent block, but also reflect such change in its descendants, in some form.

Often times, since this happens automatically when users perform a single action, like pressing a button in the Inspector Controls panel, a question might arise in them:

Why do I have to click undo twenty times to restore what I hade before clicking that button?

That's a reasonable question, and, generally speaking, this state of things is far from ideal from the experience point of view.

A few days ago I've finally found out how to avoid all of this, by using a nearly undocumented component that the Block Editor provides, called Registry, and specifically its batch method.

Here's an example of how to bundle several different actions together so that only one history item is added:

import { useRegistry } from '@wordpress/data';

const registry = useRegistry();

<Button onClick={() => {
	registry.batch( () => {
		// ...perform your operations here
	} );
}}>Click me!</Button>

There's one thing to keep in mind: with useRegistry being a low level hook in React, you're forced to use it inside a Component, namely in the edit component of your blocks, and possibly manually pass it on to any sub-Component you may have.