API Reference - @liveblocks/react

React context provider that let you use all the presence and storage hooks of @liveblocks/react.

1
import { createClient } from "@liveblocks/client";
2
import { LiveblocksProvider } from "@liveblocks/react";
3
4
const client = createClient({
5
authEndpoint: "/api/auth",
6
});
7
8
function AppRoot() {
9
return (
10
<LiveblocksProvider client={client}>
11
{ /* children */ }
12
</LiveblocksProvider>
13
);
14
}

Makes a Room available in the component hierarchy below. When this component is unmounted, the current user leave the room. That means that you can’t have 2 RoomProvider with the same room id in your react tree.

1
import { createClient, LiveList, LiveMap, LiveObject } from "@liveblocks/client";
2
import { LiveblocksProvider } from "@liveblocks/react";
3
4
const client = createClient({
5
authEndpoint: "/api/auth",
6
});
7
8
function AppRoot() {
9
return (
10
<LiveblocksProvider client={client}>
11
<RoomProvider
12
id="my-room"
13
14
// 😎 Replace with your own data!
15
initialPresence={{ cursor: { x: 0, y: 0 }}}
16
17
// 😎 Replace with your own data!
18
initialStorage={() => ({
19
animals: new LiveList(["🦁", "🦊", "🐵"]),
20
21
mathematician: new LiveObject({
22
firstName: "Ada",
23
lastName: "Lovelace",
24
}),
25
26
shapesByName: new LiveMap([
27
["apple", "🍎"],
28
["banana", "🍌"],
29
["cherry", "🍒"],
30
]),
31
})}
32
33
>
34
{/* children */}
35
</RoomProvider>
36
</LiveblocksProvider>
37
);
38
}

Returns the Room of the nearest RoomProvider above in the react component tree.

1
import { useRoom } from "@liveblocks/react";
2
3
const room = useRoom();

Returns the presence of the current user, and a function to update it.
updateMyPresence is different than the setState function returned by the useState hook from React. You don’t need to pass the full presence object to update it.

1
import { useMyPresence } from "@liveblocks/react";
2
3
const [myPresence, updateMyPresence] = useMyPresence();
4
updateMyPresence({ x: 0 });
5
updateMyPresence({ y: 0 });
6
7
// At the next render, "myPresence" will be equal to "{ x: 0, y: 0 }"

useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence. If you don’t use the current user presence in your component, but you need to update it (e.g. live cursor), it’s better to use useUpdateMyPresence to avoid unnecessary renders.

1
import { useUpdateMyPresence } from "@liveblocks/react";
2
3
const updateMyPresence = useUpdateMyPresence();
4
5
updateMyPresence({ y: 0 });

Returns an object that lets you get information about all the the users currently connected in the room.

1
import { useOthers } from "@liveblocks/react";
2
3
const others = useOthers();
4
5
// Example to map all cursors in jsx
6
{
7
others.map(({ connectionId, presence }) => {
8
if (presence == null || presence.cursor == null) {
9
return null;
10
}
11
return <Cursor key={connectionId} cursor={presence.cursor} />
12
})
13
}

Gets the current user once it is connected to the room.

1
import { useSelf } from "@liveblocks/react";
2
3
const currentUser = useSelf();

Returns a callback that let you broadcast custom events to other users in the room.

1
import { useBroadcastEvent } from "@liveblocks/react";
2
3
const broadcast = useBroadcastEvent();
4
5
broadcast({ type: "EMOJI", emoji: "🔥" });

Listen to custom events sent by other people in the room via useBroadcastEvent

1
import { useEventListener } from "@liveblocks/react";
2
3
useEventListener(({ connectionId, event }) => {
4
if (event.type === "EMOJI") {
5
// Do something
6
}
7
});

Listen to potential room connection errors.

1
import { useErrorListener } from "@liveblocks/react";
2
3
useErrorListener(error => {
4
if (error.code === 4005) {
5
// Maximum concurrent connections per room exceeded.
6
}
7
});

The storage block is in beta

The following APIs are subject to change during the beta.

The room’s storage is a conflicts-free state that multiple users can edit at the same time. It persists even after everyone leaves the room. Liveblocks provides 3 data structures that can be nested to create the state that you want.

  • LiveObject - Similar to JavaScript object. Use this for storing records with fixed key names and where the values don't necessarily have the same types. For example, a Person with a name (string) and an age (number) field.
    If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
  • LiveList - An ordered collection of items synchronized across clients. Even if multiple users add/remove/move elements simultaneously, LiveList will solve the conflicts to ensure everyone sees the same collection of items.
  • LiveMap - Similar to a JavaScript Map. Use this for indexing values that all have the same structure. For example, to store an index of Person values by their name.
    If multiple users update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
@liveblocks/react provides a set of hooks that let you interact with the room’s storage.
The data structures are mutable

LiveObject / LiveList / LiveMap are mutable which is not ideal in a react environment. We're working on an immutable version of the Storage that should make the integration even easier.

Returns the LiveObject associated with the provided key. The key should be a LiveObject instance, as populated in the initialStorage prop at the RoomProvider level. The hook returns null while the storage is loading. The hook triggers a re-render if the LiveObject is updated, however it does not triggers a re-render if a nested data structure is updated.

1
import { useObject } from '@liveblocks/react';
2
3
const object = useObject("mathematician");
4
object.get("firstName"); // => "Ada"
5
object.get("lastName"); // => "Lovelace"

Returns the LiveMap associated with the provided key. The key should be a LiveMap instance, as populated in the initialStorage prop at the RoomProvider level. The hook will return null while the storage is loading. The hook triggers a re-render if the LiveMap is updated, however it does not triggers a re-render if a nested data structure is updated.

1
import { useMap } from '@liveblocks/react';
2
3
const shapesByName = useMap("shapesByName");
4
shapesByName.get("cherry"); // => "🍒"

Returns the LiveList value at the provided key. The key should be a LiveList instance, as populated in the initialStorage prop at the RoomProvider level. The hook returns null while the storage is loading. The hook triggers a re-render if the LiveList is updated, however it does not triggers a re-render if a nested data structure is updated.

1
import { useList } from '@liveblocks/react';
2
3
const emptyList = useList("animals");
4
emptyList.get(0); // => "🦁"
5
emptyList.get(2); // => "🐵"

Returns a function that batches modifications made during the given function.
All the modifications are sent to other clients in a single message.
All the modifications are merged in a single history item (undo/redo).
All the subscribers are called only after the batch is over.

1
const batch = useBatch();
2
batch(() => {
3
// All modifications made in this callback are batched
4
});

Returns the room’s history. See Room.history for more information.

const history = useHistory();

Returns a function that undoes the last operation executed by the current client.
It does not impact operations made by other clients.

const undo = useUndo();

Returns a function that redoes the last operation executed by the current client.
It does not impact operations made by other clients.

const redo = useRedo();