Four complete examples demonstrating modern patterns for integrating Braided systems with React.
What is Braided? A minimal, type-safe library for declarative system composition with dependency-aware lifecycle management. Think dependency injection + lifecycle management for JavaScript.
What is Braided React? The bridge that lets you use Braided systems in React applications without giving up lifecycle control.
1. useSyncExternalStore - React 18 Integration ⭐ Start Here
Modern React integration using useSyncExternalStore API.
cd basic
npm install
npm run devShows:
- React 18's
useSyncExternalStoreAPI - Resources with
subscribe()andgetSnapshot()methods - Automatic re-renders without
useStateorforceUpdate - Clean, modern React patterns
Best for: Modern React apps, learning the recommended pattern
2. Zustand Integration - Stores as Resources
Zustand stores managed as Braided resources for centralized state.
cd lazy-start
npm install
npm run devShows:
- Zustand stores as Braided resources
- Multiple stores coordinated through the system
- Resources observing store changes
- Stores persisting across React remounts
Best for: Apps with complex state management, multiple stores
3. Event Bus - Loose Coupling
Resources communicating through an event bus for loose coupling.
cd singleton-manager
npm install
npm run devShows:
- Event-driven architecture
- Resources communicating via pub/sub
- Loose coupling between resources
- Observable system behavior
- Coordinated interactions without tight dependencies
Best for: Complex systems, event-driven architectures, microservices-style apps
4. Outliving React - True Independence 🔥
System that continues running even when React is unmounted.
cd outliving-react
npm install
npm run devShows:
- System persisting across React mount/unmount
- Background tasks running independently
- State preservation outside React
- True separation of concerns
- Interactive mount/unmount controls
Best for: Music players, WebSocket apps, background sync, game engines
| If you want to... | Use This Example |
|---|---|
| Learn modern React integration | useSyncExternalStore ⭐ |
| Automatic re-renders | useSyncExternalStore ⭐ |
| Manage multiple Zustand stores | Zustand Integration |
| Centralized state management | Zustand Integration |
| Loose coupling between resources | Event Bus |
| Event-driven architecture | Event Bus |
| Resources that outlive React | Outliving React 🔥 |
| Background tasks independent of React | Outliving React 🔥 |
| Music players, WebSocket connections | Outliving React 🔥 |
const counterResource = defineResource({
start: () => {
let count = 0
const listeners = new Set()
return {
subscribe: (listener) => {
listeners.add(listener)
return () => listeners.delete(listener)
},
getSnapshot: () => count,
increment: () => {
count++
listeners.forEach(l => l())
}
}
}
})
// In component
const counter = useResource('counter')
const count = useSyncExternalStore(counter.subscribe, counter.getSnapshot)const storeResource = defineResource({
start: () => {
const useStore = create((set) => ({
count: 0,
increment: () => set((s) => ({ count: s.count + 1 }))
}))
return { useStore }
}
})
// In component
const store = useResource('store')
const { count, increment } = store.useStore()const eventBusResource = defineResource({
start: () => {
const listeners = new Map()
return {
emit: (event, data) => listeners.get(event)?.forEach(h => h(data)),
on: (event, handler) => {
if (!listeners.has(event)) listeners.set(event, new Set())
listeners.get(event).add(handler)
return () => listeners.get(event).delete(handler)
}
}
}
})
// Resources communicate via events
timerResource.emit('tick', Date.now())
counterResource.on('tick', () => count++)// System starts before React
const { system } = await startSystem(config)
// Mount React
root.render(<SystemBridge system={system}><App /></SystemBridge>)
// Unmount React (system keeps running!)
root.unmount()
// Remount React (state preserved!)
root.render(<SystemBridge system={system}><App /></SystemBridge>)All examples follow these principles:
- System lives outside React - React observes, doesn't control
- Type-safe hooks - Full inference from config to components
- No ref counting - System doesn't care about React's mount/unmount
- Explicit cleanup - Halt system when truly done, not on unmount
- StrictMode proof - Resources survive double-mounting
- Day 1: useSyncExternalStore - Learn modern React integration
- Day 2: Zustand Integration - See centralized state management
- Day 3: Event Bus - Understand loose coupling
- Day 4: Outliving React - Experience true independence
- Day 5: Build your own! Mix and match patterns as needed
- Open DevTools console to see system lifecycle logs
- Try React DevTools to see how systems are just context
- Experiment with StrictMode - systems survive double-mounting
- Check the README in each example for specific details
- The "Outliving React" example has interactive mount/unmount controls!
- Modern React apps
- Clean component integration
- Automatic reactivity
- Complex state management
- Multiple coordinated stores
- E-commerce apps, dashboards
- Microservices-style architecture
- Plugin systems
- Complex coordinated workflows
- Real-time collaboration apps
- Music/video players
- WebSocket/WebRTC connections
- Background sync
- Game engines
- Session management
- Real-time chat
Untangle your code. Compose your systems. Let React observe. 🧶
- Braided - The core system composition library
- Braided React - React integration (Main Docs)
- npm: braided - Core library on npm
- npm: braided-react - React integration on npm