Skip to main content

Client SDK

In v2 all state mutations happen server-side -- clients can only read state and send actions. The server mutates state in response to actions via the onAction handler.

Installation

npm install @edgebase/web
# React Native:
npm install @edgebase/react-native

Connect

Rooms are identified by a namespace and a room ID. Ensure the user is authenticated before connecting.

import { createClient } from '@edgebase/web';
// React Native: import { createClient } from '@edgebase/react-native';

const client = createClient('https://your-project.edgebase.dev');
// ... authenticate first ...

const room = client.room('game', 'lobby-1');
await room.join();

To leave:

room.leave();

Read State

v2 has two separate state areas:

  • Shared state -- visible to all players in the room.
  • Player state -- private to each individual player.

Both are read-only on the client.

const shared = room.getSharedState();
const player = room.getPlayerState();

Subscribe to State Changes

Shared State

Called on initial sync and whenever the shared state changes. The handler receives the full state and only the changed fields (delta).

const sub = room.onSharedState((state, changes) => {
console.log('Shared state:', state);
console.log('Changes:', changes);
renderGame(state);
});

// Later: stop listening
sub.unsubscribe();

Player State

Called on initial sync and whenever the player's own state changes.

const sub = room.onPlayerState((state, changes) => {
console.log('Player state:', state);
updateInventory(state);
});

sub.unsubscribe();

Send Actions

Actions are sent to the server's onAction handler and return the server's result.

const result = await room.send('MOVE', { to: { x: 5, y: 3 } });
console.log('Move result:', result);

If the action fails server-side, the Promise rejects:

try {
await room.send('ATTACK', { target: 'player-2' });
} catch (err) {
console.error('Action failed:', err.message);
}

Messages

Listen for server-sent messages (sent by room.sendMessage() or room.sendMessageTo() in server-side code).

// Listen for a specific message type
const sub = room.onMessage('game_over', (data) => {
console.log('Winner:', data.winner);
});

sub.unsubscribe();

Listen for all messages regardless of type:

const sub = room.onAnyMessage((messageType, data) => {
console.log(`Message [${messageType}]:`, data);
});

sub.unsubscribe();

-> Server-side message sending: Server Guide


Kicked

The server can kick a player. After being kicked, auto-reconnect is disabled.

room.onKicked(() => {
console.log('You were kicked from the room');
showKickedUI();
});

-> Server-side kick setup: Server Guide


Error Handling

room.onError((err) => {
console.error(`Room error [${err.code}]: ${err.message}`);
});

Auto-Reconnect

Built-in with exponential backoff. If the WebSocket drops, the SDK automatically reconnects, re-authenticates, and triggers onSharedState / onPlayerState with the latest state. No application code needed.

Configure via options:

const room = client.room('game', 'lobby-1', {
autoReconnect: true, // default: true
maxReconnectAttempts: 10, // default: 10
reconnectBaseDelay: 1000, // default: 1000ms
sendTimeout: 10000, // default: 10000ms
});

React Native: Works transparently across app foreground/background transitions.


API Reference

Method / PropertyTypeDescription
client.room(namespace, roomId, options?)RoomClientCreate a room client
room.join()Promise<void>Connect, authenticate, and join
room.leave()voidDisconnect and clean up
room.getSharedState()Record<string, unknown>Get current shared state snapshot
room.getPlayerState()Record<string, unknown>Get current player state snapshot
room.send(actionType, payload?)Promise<unknown>Send action to server, returns result
room.onSharedState(handler)SubscriptionShared state changes -- returns { unsubscribe() }
room.onPlayerState(handler)SubscriptionPlayer state changes -- returns { unsubscribe() }
room.onMessage(type, handler)SubscriptionServer message by type -- returns { unsubscribe() }
room.onAnyMessage(handler)SubscriptionAll server messages -- returns { unsubscribe() }
room.onError(handler)SubscriptionError occurred -- returns { unsubscribe() }
room.onKicked(handler)SubscriptionKicked from room -- returns { unsubscribe() }
room.namespacestringRoom namespace
room.roomIdstringRoom instance ID