Loading...
Loading...
SpacetimeDB TypeScript/React client SDK reference. Use when building web clients that connect to SpacetimeDB.
npx skill4agent add clockworklabs/spacetimedb typescript-clienttrip_idtripIdimport React, { useMemo } from 'react';
import ReactDOM from 'react-dom/client';
import { SpacetimeDBProvider } from 'spacetimedb/react';
import { DbConnection } from './module_bindings';
import { MODULE_NAME, SPACETIMEDB_URI } from './config';
import App from './App';
const TOKEN_KEY = `${SPACETIMEDB_URI}/${MODULE_NAME}/auth_token`;
function Root() {
const connectionBuilder = useMemo(() =>
DbConnection.builder()
.withUri(SPACETIMEDB_URI)
.withDatabaseName(MODULE_NAME)
.withToken(localStorage.getItem(TOKEN_KEY) ?? undefined)
.withAutomaticReconnect()
.onConnect((_conn, _identity, token) => localStorage.setItem(TOKEN_KEY, token)),
[]
);
return (
<SpacetimeDBProvider connectionBuilder={connectionBuilder}>
<App />
</SpacetimeDBProvider>
);
}
ReactDOM.createRoot(document.getElementById('root')!).render(<Root />);import { useTable, useSpacetimeDB } from 'spacetimedb/react';
import { DbConnection, tables } from './module_bindings';
export default function App() {
const { isActive, identity: myIdentity, getConnection } = useSpacetimeDB();
const conn = getConnection() as DbConnection | null;
// useTable owns subscriptions and reports readiness after replay.
const [entities, entitiesReady] = useTable(tables.entity);
const [records, recordsReady] = useTable(tables.record);
const [onlineUsers] = useTable(
tables.entity.where(r => r.active.eq(true)),
{
onInsert: user => console.log('User connected:', user.name),
onDelete: user => console.log('User disconnected:', user.name),
onUpdate: (oldUser, newUser) => console.log('Updated:', newUser.name),
}
);
const addRecord = (data: string) => {
if (!conn || !isActive) return;
void conn.reducers.addRecord({ data }).catch(console.error);
};
const ownsEntity = entities.some(
row => row.owner.toHexString() === myIdentity?.toHexString()
);
return (
<main>
<p>{isActive ? 'Connected' : 'Not connected'}</p>
<p>{entitiesReady && recordsReady ? 'Data ready' : 'Waiting for current data'}</p>
<p>{onlineUsers.length} users online, {records.length} records</p>
<p>{ownsEntity ? 'You own an entity' : 'No owned entity'}</p>
<button disabled={!isActive} onClick={() => addRecord('Hello!')}>
Add record
</button>
</main>
);
}import { DbConnection, tables } from './module_bindings';
const HOST = 'wss://maincloud.spacetimedb.com';
const DATABASE = 'my_module';
const TOKEN_KEY = `${HOST}/${DATABASE}/auth_token`;
const conn = DbConnection.builder()
.withUri(HOST)
.withDatabaseName(DATABASE)
.withToken(localStorage.getItem(TOKEN_KEY) ?? undefined)
.withAutomaticReconnect()
.onConnect((_conn, identity, token) => {
localStorage.setItem(TOKEN_KEY, token);
console.log('Connected as:', identity.toHexString());
})
.onDisconnect((_ctx, error, nextAttempt, delayMs) => {
if (nextAttempt !== undefined) {
console.warn(`Reconnect attempt ${nextAttempt} in ${delayMs} ms`, error);
} else {
console.log('Connection ended', error);
}
})
.onConnectError((_ctx, error, nextAttempt, delayMs) => {
console.error('Connection failed:', error);
if (nextAttempt !== undefined) {
console.log(`Retry ${nextAttempt} in ${delayMs} ms`);
}
})
.build();
// Register once; the SDK replays this subscription after reconnecting.
const subscription = conn.subscriptionBuilder()
.onApplied(() => console.log('Ready'))
.subscribe([tables.user, tables.message]);
// Row callbacks
conn.db.user.onInsert((ctx, user) => console.log('Joined:', user.name));
conn.db.user.onDelete((ctx, user) => console.log('Left:', user.name));
conn.db.user.onUpdate((ctx, oldUser, newUser) => console.log('Updated:', newUser.name));myAuthauth_dataconn.subscriptionBuilder().subscribe([tables.myAuth.users]);
// Rows: conn.db.myAuth.users
// Reducers: conn.reducers.myAuth.verifyToken({ token: 'example' })
// React: useTable(tables.myAuth.users), useReducer(reducers.myAuth.verifyToken)auth_data.usersauth_data.verify_tokenconn.subscriptionBuilder().subscribe('SELECT * FROM by_id(42)');SELECT * FROM view_name(literal_args)useTable.withAutomaticReconnect()minDelayMsmaxDelayMsdisconnect().withAutomaticReconnect({ minDelayMs, maxDelayMs })disconnect()onConnectonApplieduseTableisActiveisReadyunsubscribe()conn.isReconnectingonDisconnectonConnectError(ctx, error, nextReconnectAttempt, nextReconnectDelayMs)undefinedconn.disconnect().withTokenProvider(() => refreshTokenAsync())refreshTokenAsync(): Promise<string>.withToken(initialToken)UnknownCallResultErrorspacetimedbuseTablereadonlyconst [rows] = useTable(tables.message); const sorted = [...rows].sort(...)t.u64()t.i64()bigint{Number(row.id)}{String(count)}