API Reference - @liveblocks/client

Create a client that will be responsible to communicate with liveblocks servers.

When creating a client with a public key, you don’t need to setup an authorization endpoint

1
2
3
import { createClient } from "@liveblocks/client";
const client = createClient({ publicApiKey: "pk_live_XXXXXXXXXXXX" });

If you are not using a public key, you need to setup your own authEndpoint. Please refer to our Authentication guide.

1
2
3
import { createClient } from "@liveblocks/client";
const client = createClient({ authEndpoint: "/api/auth" });

If you need to add additional headers or use your own function to call the endpoint, authEndpoint also supports a callback.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { createClient } from '@liveblocks/node';
const client = createClient({
authEndpoint: async (room) => {
const response = await fetch("/api/auth", {
method: "POST",
headers: {
Authentication: "token",
"Content-Type": "application/json"
},
body: JSON.stringify({ room })
});
return await response.json();
}
});

Client returned by createClient.

Enters a room and returns it. The authentication endpoint is called as soon as you call this function.
The second argument is the presence of the current user when joining the room. If ommited, other users will receive and empty object. The presence will be serializable to JSON.

const room = client.enter("my-room", { cursor: null });

Leaves a room.

client.leave("my-room");

Gets a room by id. Returns null if Client.enterhas not been called previously.

const room = client.getRoom("my-room");

Room returned by Client.enteror Client.getRoom.

Gets the presence of the current user.

const presence = room.getPresence();

Updates the presence of the current user. Only pass the properties you want to update. No need to send the full presence.

1
2
3
4
5
room.updatePresence({ x: 0 });
room.updatePresence({ y: 0 });
const presence = room.getPresence();
// presence is equivalent to { x: 0, y: 0 }

Gets all the other users in the Room.

const others = room.getOthers();

Broadcast an event to other users in the Room. Event broadcasted to the room can be listened with Room.subscribe("events"). Takes a payload as first argument. Should be serializable to JSON.

1
2
3
4
5
6
7
8
9
// On client A
room.broadcastEvent({ type: "EMOJI", emoji: "πŸ”₯" });
// On client B
room.subscribe("event", ({ event }) => {
if(event.type === "EMOJI") {
// Do something
}
});

Subscribe to the current user presence updates.
Takes a callback that is called every time the current user presence is updated with Room.updatePresence.

1
2
3
room.subscribe("my-presence", (presence) => {
// Do something
});

Unsubscribe to the current user presence updates.
Takes a callback that has been previously used with Room.subscribe("my-presence").

1
2
3
const onPresenceChange = (presence) => { };
room.subscribe("my-presence", onPresenceChange);
room.unsubscribe("my-presence", onPresenceChange);

Subscribe to the other users updates.
Takes a callback that is called when a user enters or leaves the room or when a user update its presence.

1
2
3
room.subscribe("others", (presence) => {
// Do something
});

Unsubscribe to the other users updates.
Takes a callback that has been previously used with Room.subscribe("others").

1
2
3
const onOthersChange = (presence) => { };
room.subscribe("others", onOthersChange);
room.unsubscribe("others", onOthersChange);

Subscribe to events broadcasted by Room.broadcastEvent.
Take a callback that is called when a user calls Room.broadcastEvent.

1
2
3
room.subscribe("event", ({ event, connectionId }) => {
// Do something
});

Unsubscribe to events broadcasted by Room.broadcastEvent.
Takes a callback that has been previously used with Room.subscribe("events").

1
2
3
const onEvent = ({ event, connectionId }) => { };
room.subscribe("event", onEvent);
room.unsubscribe("event", onEvent);

The storage block is in private beta

If we didn’t give you access explicitly, the following APIs will not work. 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. If multiple users 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. If multiple users update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.

Get the room's storage asynchronously (returns a Promise). The storage's root is a LiveObject.

const { root } = await room.getStorage();

The LiveObject class is similar to a JavaScript object that is synchronized on all clients. Keys should be a string, and values should be serializable to JSON. If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.

Create an empty LiveObject

const object = new LiveObject();

Create a LiveObject with initial data

const object = new LiveObject({ firstName: "Margaret", lastName: "Hamilton" });

Get a property from the LiveObject

1
2
const object = new LiveObject({ firstName: "Ada", lastName: "Lovelace" });
object.get("firstName"); // equals to "Ada"

Adds or updates a property with the specified key and a value.

1
2
const object = new LiveObject({ firstName: "Marie" });
object.set("lastName", "Curie");

Subscribes to updates. In a future version, you will be able to know exactly what changed.

1
2
3
4
5
const object = new LiveObject({ firstName: "Grace", lastName: "Hopper" });
object.subscribe(() => {
// Executed when the object is updated
});

Subscribes to updates and children updates. In a future version, you will be able to know exactly what changed.

1
2
3
4
5
6
7
8
9
10
const scientist = new LiveObject({ firstName: "Grace", lastName: "Hopper" });
const awards = new LiveList();
scientist.set("awards", awards);
scientist.subscribeDeep(() => {
// Executed when awards is updated
});
awards.push("Presidential Medal of Freedom");

Transform the LiveObject into a javascript object

1
2
const liveObject = new LiveObject({ firstName: "Grace", lastName: "Hopper" });
liveObject.toObject(); // equals to { firstName: "Grace", lastName: "Hopper" }

Adds or updates multiple properties at once.

1
2
const object = new LiveObject({ firstName: "Grace", lastName: "Hopper" });
object.update({ job: "Computer Scientist", birthDate: "December 9, 1906" });

The LiveMap class is similar to a JavaScript Map that is synchronized on all clients. Keys should be a string, and values should be serializable to JSON. If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.

Create an empty LiveMap

const map = new LiveMap();

Create a LiveMap with initial data

const map = new LiveMap([["keyA", "valueA"], ["keyB", "valueB"]]);

Removes the specified element by key. Returns true if an element existed and has been removed, or false if the element does not exist.

1
2
3
4
const map = new LiveMap([["keyA", "valueA"], ["keyB", "valueB"]]);
map.delete("keyA"); // equals true
map.get("keyA"); // equals undefined
map.delete("unknownKey"); // equals false

Returns a new Iterator object that contains the [key, value] pairs for each element.

1
2
3
for(const [key, value] of map.entries()) {
// Iterate over all the keys and values of the map
}

Returns a specified element from the LiveMap or undefined if the key can’t be found.

1
2
3
const map = new LiveMap([["keyA", "valueA"], ["keyB", "valueB"]]);
map.get("keyA"); // equals "valueA"
map.get("unknownKey"); // equals undefined

Returns a boolean indicating whether an element with the specified key exists or not.

1
2
3
const map = new LiveMap([["keyA", "valueA"], ["keyB", "valueB"]]);
map.has("keyA"); // equals true
map.has("unknownKey"); // equals false

Returns a new Iterator object that contains the the keys for each element.

1
2
3
for(const key of map.keys()) {
// Iterate over all the keys and values of the map
}

Adds or updates an element with a specified key and a value.

1
2
const map = new LiveMap();
map.set("keyA", "valueA");

Returns the number of elements in the LiveMap.

1
2
const map = new LiveMap([["keyA", "valueA"], ["keyB", "valueB"]]);
map.size; // equals 2

Subscribes to updates. In a future version, you will be able to know exactly what changed.

1
2
3
4
5
const map = new LiveMap();
map.subscribe(() => {
// Executed when the map is updated
});

Subscribes to updates and children updates. In a future version, you will be able to know exactly what changed.

1
2
3
4
5
6
7
8
9
10
const map = new LiveMap();
const mathematician = new LiveObject({ firstName: "Ada" });
map.set("id", mathematician);
map.subscribeDeep(() => {
// Executed when mathematician is updated
});
mathematician.set("lastName", "Lovelace");

Returns a new Iterator object that contains the the values for each element.

1
2
3
for(const value of map.values()) {
// Iterate over all the values of the map
}

The LiveList class represents an ordered collection of items that is synchorinized across clients. Items should be serializable to JSON or another Live data structure.

Create an empty LiveList

const list = new LiveList();

Create a LiveMap with initial data

const list = new LiveList(["🦁", "🦊", "🐡"]);

Deletes an element at the specified index.

1
2
3
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.delete(1);
list.toArray(); // equals ["🦁", "🐡"]

Tests whether all elements pass the test implemented by the provided function. Returns true if the predicate function returns a truthy value for every element. Otherwise, false.

1
2
3
4
const list = new LiveList([0, 2, 4]);
list.every(i => i % 2 === 0); // equals true
list.push(5);
list.every(i => i % 2 === 0); // equals false

Creates an array with all elements that pass the test implemented by the provided function.

1
2
const list = new LiveList([0, 1, 2, 3, 4]);
list.filter(i => i % 2 === 0); // equals [0, 2, 4]

Returns the first element that satisfies the provided testing function.

1
2
const list = new LiveList(["apple", "lemon", "tomato"]);
list.find(fruit => fruit.startsWith("l")); // equals "lemon"

Returns the index of the first element in the LiveList that satisfies the provided testing function.

1
2
const list = new LiveList(["apple", "lemon", "tomato"]);
list.find(fruit => fruit.startsWith("l")); // equals 1

Executes a provided function once for each element.

1
2
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.forEach(item => console.log(item)); // prints to the console "🦁", "🦊", "🐡"

Get the element at the specified index.

1
2
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.get(2); // equals "🐡"

Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.

1
2
3
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.indexOf("🐡"); // equals 2
list.indexOf("🐺"); // equals -1

Inserts one element at a specified index.

1
2
3
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.insert(1, "🐺");
list.toArray(); // equals ["🦁", "🐺", "🦊", "🐡"]

Returns the last index at which a given element can be found in the LiveList, or -1 if it is not present. The LiveList is searched backwards, starting at fromIndex.

1
2
3
const list = new LiveList(["🦁", "🦊", "🐡", "🦊"]);
list.lastIndexOf("🦊"); // equals 3
list.lastIndexOf("🐺"); // equals -1

Returns the number of elements.

1
2
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.length; // equals 3

Creates an array populated with the results of calling a provided function on every element.

1
2
const list = new LiveList(["apple", "lemon", "tomato"]);
list.map(fruit => fruit.toUpperCase()); // equals ["APPLE", "LEMON", "TOMATO"]

Inserts one element at a specified index.

1
2
3
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.move(2, 0); // move the "🐡" at index 0
list.toArray(); // equals ["🐡", "🦁", "🦊"]

Adds one element to the end of the LiveList.

1
2
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.toArray(); // equals ["🦁", "🦊", "🐡", "🐺"]

Tests whether at least one element in the LiveList passes the test implemented by the provided function.

1
2
3
const list = new LiveList(["apple", "lemon", "tomato"]);
list.some(fruit => fruit.startsWith("l")); // equals true
list.some(fruit => fruit.startsWith("x")); // equals false

Subscribes to updates. In a future version, you will be able to know exactly what changed.

1
2
3
4
5
const list = new LiveList(["apple", "lemon", "tomato"]);
list.subscribe(() => {
// Executed when the list is updated
});

Subscribes to updates and children updates. In a future version, you will be able to know exactly what changed.

1
2
3
4
5
6
7
8
9
10
const authors = new LiveList();
const mathematician = new LiveObject({ firstName: "Ada" });
authors.push(mathematician);
authors.subscribeDeep(() => {
// Executed when mathematician is updated
});
mathematician.set("lastName", "Lovelace");

Returns an Array of all the elements in the LiveList.

1
2
const list = new LiveList(["🦁", "🦊", "🐡"]);
list.toArray(); // equals ["🦁", "🦊", "🐡"]