Getting started—React tutorial
Storage
Storage allows us to create persistent data that multiple users can edit simultaneously. This is ideal for storing realtime document state, such as shapes on a canvas, paragraphs in a text editor, or cells in a spreadsheet.
Storage is part of our Sync Datastore product.
Conflict-free data types
To build applications using storage, you can make use of our conflict-free data types. Each type is similar to a JavaScript counterpart:
LiveObject- JavaScript ObjectLiveList- JavaScript ArrayLiveMap- JavaScript Map
These data types can be combined and nested, to create a realtime data structure that automatically updates when multiple users modify data at the same time, whilst handling any conflicts along the way.
Defining storage
Let’s imagine we were storing some data about a person, for example their name and age.
person: { name: "Marie", age: 30 }To add this to storage, first we must define our types. Open
liveblocks.config.ts and use a LiveObject with the structure for
person as a generic.
/liveblocks.config.ts// Storage typeStorage: { person: LiveObject<{ name: string; age: number; }>;}Now we’ve defined the type, we can switch to App.tsx and add an
intialStorage value, that is used when the room’s storage is created. We can
match the Storage type by creating a new LiveObject.
/App.tsx<RoomProvider id={roomId} initialStorage={{ person: new LiveObject({ name: "Marie", age: 30 }), }}>Using a LiveObject like this, instead of a regular JavaScript object, allows us to use its realtime features. For example multiple people can edit the properties of a LiveObject at the same time without overriding the whole object.
Displaying storage
To use this realtime data in your app, we can import a hook named
useStorage. This hook allows us to select part of our storage, before
returning its value, and automatically updating on realtime changes.
// { person: "Marie", age: 30 }const person = useStorage((root) => root.person);Each realtime data structure is converted to an immutable copy of its
JavaScript counterpart, so a LiveObject becomes a regular JavaScript object.
We can implement this ourselves by adding the following code to Room.tsx:
/Room.tsximport { useStorage } from "@liveblocks/react/suspense";
export function Room() { const person = useStorage((root) => root.person);
return <div>Person: {JSON.stringify(person)}</div>;}If we weren’t using suspense in our config file, person would return null
until it was loaded, and we’d have to check for this. We’re using suspense
here, so this isn’t a worry.
Press the refresh button in the preview window to reload initialStorage,
and you should now be seeing person! On the next page we’ll be updating
storage.