@roomservice/react
The @roomservice/react
library is the main JS library for RoomService. You should use it with the @roomservice/browser
library.
Installing
npm install --save @roomservice/react@next
or, with yarn:
yarn add @roomservice/react@next
Usage
<RoomServiceProvider />
Setup a At the top of your app, add a RoomServiceProvider
with your auth endpoint.
import { RoomServiceProvider } from "@roomservice/react";
function App() {
return (
<RoomServiceProvider authUrl="https://yoursite.com/api/roomservice">
<CollaborativeComponent />
</RoomServiceProvider>
);
}
export default App;
useSharedState
Shared state lets you and other folks in the room collaborate on the same JSON state. Shared state has a built-in CRDT and offline support, so you can assume that merges will happen automatically, deterministically, and without the need for constant internet connection.
import { useSharedState } from "@roomservice/react";
function MyComponent() {
const [sharedState, setSharedState] = useSharedState("my-room");
function onChange() {
setSharedState(prevState => {
prevState.myOption = "hello!";
});
}
// ...
}
Rules of sharedState
Rule 1: only use a function parameter. Unlike the regular setState
, setSharedState
only supports a function as an argument, not an object.
For example:
// BAD - not allowed
setSharedState({
title: "hello!"
});
// GOOD - this works
setSharedState(prevState => {
prevState.title = "hello!";
});
Rule 2: don't return anything. As you may have noticed, the function you pass into setSharedState
does not return anything from the document like setState
does. Instead, it works like Immer does; you mutate the object itself.
For example:
// BAD - don't return
setSharedState(prevState => {
return {
...prevState,
title: "hello!"
};
});
// GOOD - mutate the object instead
setSharedState(prevState => {
prevState.title = "hello!";
});
Rule 3: only JSON primitives. Don't pass classes, functions, or React components into your shared state. Only JSON primitives, like lists, numbers, strings, and maps work. As a rule of thumb, if it wouldn't be valid in someFile.json
, it won't be valid in Room Service.
For example:
class MyBike {
zoom() {}
}
// BAD - this won't work like you expect
setSharedState(prevState => {
prevState.bike = new MyBike();
});
usePresence
Presence is temporary state for each individual user in a room that, like shared-state, updates automatically. Presence is not stored in a CRDT and does not do automatic merging.
Unlike shared state, presence has extremely low latency, which makes it perfect for:
- Mouse cursors
- GPS locations
- the cell position in a table
- device info
- the tab someone's on
- ???
import { usePresence } from "@roomservice/react";
const [positions, setMyPosition] = usePresence("my-room", "cell-positions");
// Set your presence.
setMyPosition({
x: 0,
y: 10
});
// Access other user's presence
const { x, y } = positions["my-user-reference"];
Note that presence returns an object, not an array. So if you want to iterate through multiple folks presences, you should use Object.values
.
function MapPins() {
const [locations, setMyPresence] = usePresence("my-room", "locations");
Object.values(locations).map(location => {
return <Pin lat={location.lat} long={location.long} >
})
}
Presence is meant to be a primitive to make other declarative real-time features. So get creative and make your own custom hooks!