React SDK integration
Use this guide to wirenodalmerge-sdk-js into a React app without leaking subscriptions or fighting React render lifecycles.
The pattern below works for small apps and scales into larger state architectures.
Install
Integration strategy
In React, treat the SDK instance as long-lived room/session state. Recommended approach:- Create SDK once per room/session boundary
- Connect on mount
- Subscribe to runtime/change events
- Unsubscribe and close on cleanup
Minimal hook pattern
React state update pattern
Use SDK events to invalidate React state snapshots, then read current SDK values. Typical flow:- Subscribe to runtime/change event
- Read required keys/projections
- Update React state atomically
Optimistic UI in React
Model optimistic actions with intent lanes and render pending state immediately. Then refine UI from canonical lane updates:- Intent write updates pending UI fast
- Canonical updates confirm/override outcomes
- Rejection events drive user-visible correction
Presence in React components
Presence state should be component-friendly but ephemeral. Pattern:- Set local presence in focused/active components
- Subscribe to peer presence snapshots
- Clean up listeners and optionally clear presence on unmount
Persistence and hydration
For robust React experiences, enable local persistence and test refresh/reopen behavior. Checklist:- Hydration runs before critical UI depends on room state
- Loading states account for initial hydration lag
- Reconnect paths do not reset user-visible local edits unexpectedly
Error and rejection handling in UI
In React, route SDK errors into explicit UI state:- Toast/banner for actionable user errors
- Structured debug panel for developer/operator context
- Retriable actions for transport/transient failures
Performance tips
- Keep one SDK instance per active room, not per component
- Use context/provider boundaries to share room instance
- Batch React state updates from event streams where possible
- Unsubscribe every listener in cleanup paths
Common mistakes
- Creating SDK in render body
- Registering listeners without cleanup
- Coupling component render frequency to
sdk.sync.push()calls - Mixing intent/canonical keys in one local selector
- Ignoring reconnect transitions in UI state machine