API Reference
createClient
Returns a PluvClient
instance
This is a re-export of createClient from @pluv/client.
createBundle
Returns a CreateBundle
instance
Creates a bundle to be able to access the PluvClient
and PluvRoom
from various react hooks.
import { createBundle createClient } from "@pluv/react";
import { yjs } from "@pluv/crdt-yjs";
const io = createClient({
// ...
});
// Destructured room bundle
export const {
// components
MockedRoomProvider,
PluvProvider,
PluvRoomProvider,
// utils
event,
// hooks
useBroadcast,
useCanRedo,
useCanUndo,
useClient,
useConnection,
useDoc,
useEvent,
useMyPresence,
useMyself,
useOther,
useOthers,
useRedo,
useRoom,
useStorage,
useTransact,
useUndo,
} = createBundle(io);
CreateBundle
This is the bundle returned from createBundle
.
MockedRoomProvider
React provider component to mock PluvRoomProvider
. Enables hooks from CreateBundle
while completely offline. This can be useful in Storybook within a storybook decorator when mocking PluvRoomProvider
.
import { yjs } from "@pluv/crdt-yjs";
import { MockedRoomProvider } from "./io";
const MyComponent: FC = () => {
return (
<MockedRoomProvider
/**
* @description Mock events sent and received for hooks in child components.
*/
//
events={{
EMIT_EMOJI: ({ emojiCode }) => ({
EMOJI_RECEIVED: { emojiCode },
}),
}}
/**
* @optional
* @description Define your initial presence
*/
initialPresence={{
selectionId: null,
}}
/**
* @optional
* @description Define the initial storage for the room, as well as the CRDT to use
*/
initialStorage={() => ({
messages: yjs.array(),
})}
/**
* @required
* @description Set the room id
*/
room="my-mock-room"
>
{children}
</MockedRoomProvider>
);
};
PluvProvider
React provider component to allow the PluvClient
created by createClient
to be accessible in child components via useClient
. This is identical to importing the created client, so this is primarily useful for dependency injection when testing.
<PluvProvider>{children}</PluvProvider>
PluvRoomProvider
React provider component to enable CreateBundle
hooks within child components. Mounting this component connects to a real-time room with other connected users. Unmounting this component will disconnect the room. See Create Rooms for more details.
import { yjs } from "@pluv/crdt-yjs";
import { MockedRoomProvider } from "./io";
const MyComponent: FC = () => {
return (
<PluvRoomProvider
/**
* @optional
* @description Define the user's initial presence
*/
initialPresence={{
selectionId: null,
}}
/**
* @optional
* @description Define the initial storage for the room
*/
initialStorage={() => ({
messages: yjs.array(),
})}
/**
* @optional
* @description Emits an error whenever authorization fails, for
* monitoring or debugging purposes
*/
onAuthorizationFail={(error: Error) => {
console.error(error);
}}
/**
* @required
* @description Set the room id
*/
room="my-room-id"
>
{children}
</PluvRoomProvider>
);
};
event
Returns EventProxy
Defines an event listener client for events broadcasted by connected clients. See useEvent for more details.
// The below 2 statements are equivalent
useEvent("receiveMessage", ({ data }) => {
console.log(data.message);
});
event.receiveMessage.useEvent(({ data }) => {
console.log(data.message);
});
useBroadcast
Returns BroadcastProxy
Returns a broadcast function to emit an event and data to all connected clients. This is type-safe. The first parameter event
will be the name of the event procedure specified when creating your PluvProcedure
instance, and the second parameter data
will be the associated input type. See Define Events for more details.
const broadcast = useBroadcast();
// The below 2 statements are equivalent
broadcast("sendMessage", { message: "Hello world~!" });
broadcast.sendMessage({ message: "Hello world~!" });
useCanRedo
Returns boolean
Checks whether calling PluvRoom.redo will mutate storage.
const canRedo: boolean = useCanRedo();
useCanUndo
Returns boolean
Checks whether calling PluvRoom.undo will mutate storage.
const canUndo: boolean = useCanUndo();
useClient
Returns PluvClient
Returns the PluvClient
that was created via createClient
.
useConnection
Returns WebSocketConnection
Returns the websocket connection start of the current user.
const connection = useConnection();
// ^? const connection: {
// id: string | null;
// state: ConnectionState;
// }
useDoc
Returns AbstractCrdtDoc
This returns an instance of the AbstractCrdtDoc
that holds the underlying CRDT doc. For instance, when using @pluv/crdt-yjs
, this will hold a yjs doc in its value
property.
import { yjs } from "@pluv/crdt-yjs";
import { Doc as YDoc } from "yjs";
const doc: yjs.CrdtYjsDoc<any> = useDoc();
const ydoc: YDoc = doc.value;
useEvent
Returns void
Defines a listener for events broadcasted by connected clients. This is type-safe. The first parameter event
is the name of the event to listen to from your backend PluvIO
instance. The second parameter is a callback containing the data emitted from the broadcasted event.
useEvent("EMOJI_RECEIVED", ({ emojiCode }) => {
console.log(emojiCode);
});
useMyPresence
Returns [myPresence: TPresence | null, updatePresence: Function]
Returns the current user's presence, and a function to update the user's presence. Using this hook rerenders the component based on a deep-equality check on the user's presence value. This hook accepts a selector to return a modified presence to reduce rerenders.
const io = createClient({
presence: z.object({
selectionId: z.string().nullable(),
selectionColor: z.string(),
}),
// ...
});
// ...
const { useMyPresence } = createBundle(io);
const [
// the user's presence
myPresence,
// a presence updater function
updateMyPresence
] = useMyPresence();
// update individual base properties
updateMyPresence({ selectionId: "name-input" });
updateMyPresence({ selectionColor: "#123456" });
// update multiple base properties
updateMyPresence({
selectionId: "name-input",
selectionColor: "#123456",
});
// if you only need a partial presence
const [myPresence] = useMyPresence(({ selectionId }) => selectionId);
// if you don't need presence, and just want the updater
const [, updateMyPresence] = useMyPresence(
// set selector to return a stable value
() => true
);
useMyself
Returns UserInfo | null
Returns the user-info object for the current user. This hook accepts a selector to return a modified user-info to reduce rerenders.
const myself = useMyself();
// if you don't need the entire user-info
const myself = useMyself(({ connectionId }) => connectionId);
useOther
Returns UserInfo | null
Returns the user-info object for a connected user by connectionId
string.
const other = useOther();
// if you don't need the entire user-info
const other = useOther(({ connectionId }) => connectionId);
useOthers
Returns readonly UserInfo[]
Returns all user-info objects for all connected users. This may trigger a lot of re-renders if presence updates frequently.
Note Consider using this hook only for deriving others'
connectionId
values to pass intouseOther
.
const others = useOthers();
// if you want to just pull out connectionId properties
const connectionIds = useOthers((others) => {
return others.map(({ connectionId }) => connectionId);
});
useRedo
Returns void
Re-applies the last mutation that was undone via PluvRoom.undo.
For more information see: History
const redo = useRedo();
redo();
useStorage
Returns [TData | null, AbstractCrdtType | null]
Returns a base-level property of our CRDT storage as a serialized value and a @pluv/crdt
AbstractCrdtType
that holds a shared type of our specified CRDT. The component is re-rendered whenever the AbstractCrdtType
is updated. The returned values are null while the room is still connecting or
initializing its storage.
import { yjs } from "@pluv/crdt-yjs";
const io = createClient({
initialStorage: yjs.doc(() => ({
messages: yjs.array(["hello"]),
})),
// ...
});
// ...
const { useStorage } = createBundle(io);
const [messages, sharedType] = useStorage("messages");
sharedType.push(["world~!"]);
messages.map((message, key) => <div key={key}>{message}</div>);
useTransact
Returns void
Performs a mutation that can be tracked as an operation to be undone/redone (undo/redo). When called without an origin, the origin will default to the user's connection id.
You can specify a 2nd parameter to transact with a different transaction origin.
For more information see: History
const [messages, sharedType] = useStorage("messages");
const transact = useTransact();
transact((tx) => {
sharedType.push(["hello world!"]);
// Alternatively, access your storage from here
tx.messages.push(["hello world!"]);
});
// This will also be undoable if `"user-123"` is a tracked origin.
transact(() => {
sharedType.push(["hello world!"]);
}, "user-123");
useUndo
Returns void
Undoes the last mutation that was applied via PluvRoom.transact.
For more information see: History
const undo = useUndo();
undo();