@siltrun/react
v0.1.2
Published
Silt React binding — useRoom(url, { id }) → { state, send } over one @siltrun/client connection.
Maintainers
Readme
@siltrun/react
The React binding for Silt. One hook wraps the @siltrun/client
connection so a component reads authoritative room state and sends intent — no provider,
no store wiring.
npm install @siltrun/reactuseRoom
const { state, send } = useRoom<GameState>(url, { id });state— the room's latest authoritative state, typedGameState | undefined:undefineduntil the first server broadcast arrives; the component re-renders on every update after that. The type parameter is your declared shape of the room state (the wire is untyped JSON — it's a cast, not a runtime check); omit it andstateisunknown.send(data)— droppable datagram intent (latest-wins), for high-frequency signals like pointer position.send(data, { reliable: true })routes on the ordered event lane.id— a stable client identity, captured once at mount. A fresh value each render (e.g. an inlinecrypto.randomUUID()) still means one identity per mounted component.
Connections dedupe by url + id at module scope: two components pointed at the same room
share a single socket, and the last unmount closes it. StrictMode-safe.
The full client (from the quickstart)
import { useRoom } from "@siltrun/react";
type GameState = { ships: Record<string, { x: number; y: number }> };
export default function Game() {
const { state, send } = useRoom<GameState>("http://localhost:4000", { id: crypto.randomUUID() });
if (!state) return <p>joining…</p>;
return (
<svg width={520} height={280} style={{ background: "#050505" }}
onPointerMove={(e) => send({ x: e.nativeEvent.offsetX, y: e.nativeEvent.offsetY })}>
{Object.entries(state.ships).map(([id, s]) => (
<circle key={id} cx={s.x} cy={s.y} r={8} fill="#f59e0b" />
))}
</svg>
);
}That exact file is kept typechecked against a stock Vite TS template, so it compiles as written.
Open two tabs and drag in one: the ship moves in both, driven by the server. send() is
your intent, state is the authoritative world. The full walkthrough is at
https://silt.run/docs/quickstart/.
Peer dependency: react >= 18 (the hook uses useSyncExternalStore).
Docs
Full guides and API reference: https://silt.run/docs/
