Introduction
Building multiplayer applications presents unique challenges that single-user apps never face: multiple sources of truth, network latency, conflicting updates, and the need for immediate feedback.
**What you'll build**: A real-time collaborative whiteboard application that handles concurrent edits gracefully.
Prerequisites
The Core Problem
When two users edit the same data simultaneously, you face the classic concurrent update problem:
// User A sends at t=100ms
{ action: 'move', shapeId: '1', x: 100, y: 200 }
// User B sends at t=101ms
{ action: 'move', shapeId: '1', x: 150, y: 250 }
// Which update wins?Implementing Optimistic Updates
Don't wait for server confirmation—update the UI immediately:
const moveShape = (id: string, x: number, y: number) => {
// Update locally first
updateLocalState(id, x, y, { optimistic: true });
// Then send to server
ws.send(JSON.stringify({ type: 'MOVE_SHAPE', id, x, y }));
};Conflict Resolution
Use a deterministic strategy for resolving conflicts:
function resolveConflict(localOp: Operation, remoteOp: Operation): Operation {
if (remoteOp.timestamp > localOp.timestamp) return remoteOp;
if (remoteOp.timestamp === localOp.timestamp) {
return remoteOp.clientId > localOp.clientId ? remoteOp : localOp;
}
return localOp;
}Common Pitfalls
**Avoid storing WebSocket in React state** — use `useRef` to prevent unnecessary re-renders.
**Implement reconnection logic** — connections drop; always handle reconnects gracefully.
Conclusion
Real-time state management requires careful thought about optimistic updates, conflict resolution, and reconnection handling. Start simple and add complexity only when needed.