How to use Liveblocks multiplayer undo/redo with React
In this guide, we’ll be learning how to use Liveblocks multiplayer undo/redo
with React using the hooks from the @liveblocks/react
package.
This guide uses TypeScript. Liveblocks can definitely be used without TypeScript. We believe typings are helpful to make collaborative apps more robust, but if you’d prefer to skip the TypeScript syntax, feel free to write your code in JavaScript.
Multiplayer undo/redo
Implementing undo/redo in a multiplayer environment is
notoriously complex,
but Liveblocks provides functions to handle it for you. useUndo
and useRedo
return functions that allow you to undo and redo the last changes made to your
app.
An example of this in use would be a button that updates the current firstName
of a scientist. Every time a Liveblocks storage change is detected, in this case
.set
being called, it’s stored. Pressing the undo button will change the name
back to its previous value.
Multiplayer undo/redo is much more complex that it sounds—if you’re interested in the technical details, you can find more information in our interactive article: How to build undo/redo in a multiplayer environment.
Pause and resume history
Sometimes it can be helpful to pause undo/redo history, so that multiple updates are reverted with a single call.
For example, let’s consider a design tool; when a user drags a rectangle, the
intermediate rectangle positions should not be part of the undo/redo history,
otherwise pressing undo
may only move the rectangle one pixel backwards.
However, these small pixel updates should still be transmitted to others, so
that the transition is smooth.
useHistory
is a hook that allows us to pause and resume history states as we
please.
Presence history
By default, undo/redo only impacts the room storage—there’s generally no need to use it with presence, for example there’s no reason to undo the position of a user’s cursor. However, occasionally it can be useful.
If we explore the design tool scenario, the currently selected rectangle may be
stored in a user’s presence. If undo
is pressed, and the rectangle is moved
back, it would make sense to remove the user’s selection on that rectangle.
To enable this, we can use the addToHistory
option when updating the user’s
presence.
This also works in mutations with setMyPresence
.