|
| 1 | +# Building a Counter with @webrtc-remote-control/react |
| 2 | + |
| 3 | +## Application Behavior |
| 4 | +This application creates a real-time counter that can be controlled remotely: |
| 5 | + |
| 6 | +1. **Master Device (e.g., Laptop)** |
| 7 | + - Displays a QR code on the screen |
| 8 | + - Shows the current counter value |
| 9 | + - Updates in real-time when remote devices interact |
| 10 | + - Can display multiple connected remote devices and their counter values |
| 11 | + |
| 12 | +2. **Remote Device (e.g., Smartphone)** |
| 13 | + - User scans the QR code from the master device |
| 14 | + - Opens a simple interface with + and - buttons |
| 15 | + - Each button press instantly updates the counter on the master device |
| 16 | + - Connection status is clearly displayed |
| 17 | + |
| 18 | +The library does handle all the WebRTC communication automatically, making the counter update in real-time across devices. It also handles any reload of the page, and will reconnect to the same peer if the page is reloaded. |
| 19 | + |
| 20 | +## Application Structure |
| 21 | +``` |
| 22 | +Root |
| 23 | +└── WebRTCRemoteControlProvider |
| 24 | + ├── Master (displays QR code & counter) |
| 25 | + └── Remote (shows + and - buttons) |
| 26 | +``` |
| 27 | + |
| 28 | +## Prerequisites |
| 29 | +The library is a wrapper for [PeerJS](https://peerjs.com/), you will need to include the PeerJS library in your project. |
| 30 | + |
| 31 | +## Mode Configuration |
| 32 | +You should determine the mode based on the URL: |
| 33 | +- `mode="master"`: When accessing the page directly |
| 34 | +- `mode="remote"`: When the URL contains a hash (peer ID) |
| 35 | + |
| 36 | +For example: |
| 37 | +- `https://your-app.com` → Set `mode="master"` |
| 38 | +- `https://your-app.com#abc123` → Set `mode="remote"` |
| 39 | + |
| 40 | +## Getting Started |
| 41 | +The library does automatically handle WebRTC connections, but you should: |
| 42 | +1. Wrap your application with `WebRTCRemoteControlProvider` |
| 43 | +2. Implement Master and Remote components |
| 44 | +3. Use the `usePeer` hook for WebRTC communication |
| 45 | + |
| 46 | +## Implementation Guide |
| 47 | + |
| 48 | +### 1. Root Component Setup |
| 49 | +You should initialize the WebRTC context like this: |
| 50 | +```jsx |
| 51 | +<WebRTCRemoteControlProvider |
| 52 | + mode={mode} |
| 53 | + init={({ getPeerId }) => new Peer(getPeerId(), getPeerjsConfig())} |
| 54 | + masterPeerId={window.location.hash?.replace("#", "") || null} |
| 55 | + sessionStorageKey="webrtc-remote-control-peer-id-react" |
| 56 | +> |
| 57 | +``` |
| 58 | +
|
| 59 | +### 2. Master Component Implementation |
| 60 | +The library does provide: |
| 61 | +- WebRTC connection management |
| 62 | +- Peer discovery and connection |
| 63 | +- Real-time data transmission |
| 64 | +- Connection state handling |
| 65 | +- QR code generation for peer ID |
| 66 | +
|
| 67 | +You should implement: |
| 68 | +- Counter state management (increment/decrement logic) |
| 69 | +- Display of current counter value |
| 70 | +- List of connected remotes and their individual counters |
| 71 | +- UI for the master view |
| 72 | +- Error handling specific to counter operations |
| 73 | +
|
| 74 | +Here's a minimal Master component: |
| 75 | +```jsx |
| 76 | +function Master() { |
| 77 | + const { ready, api, peer } = usePeer(); |
| 78 | + const [remotesList, setRemotesList] = useState([]); |
| 79 | + |
| 80 | + useEffect(() => { |
| 81 | + if (ready) { |
| 82 | + // Handle remote connections |
| 83 | + api.on("remote.connect", ({ id }) => { |
| 84 | + setRemotesList(prev => [...prev, { id, counter: 0 }]); |
| 85 | + }); |
| 86 | + |
| 87 | + // Handle remote disconnections |
| 88 | + api.on("remote.disconnect", ({ id }) => { |
| 89 | + setRemotesList(prev => prev.filter(remote => remote.id !== id)); |
| 90 | + }); |
| 91 | + |
| 92 | + // Handle incoming counter commands |
| 93 | + api.on("data", ({ id }, data) => { |
| 94 | + if (data.type === "COUNTER_INCREMENT") { |
| 95 | + setRemotesList(prev => |
| 96 | + prev.map(remote => |
| 97 | + remote.id === id |
| 98 | + ? { ...remote, counter: remote.counter + 1 } |
| 99 | + : remote |
| 100 | + ) |
| 101 | + ); |
| 102 | + } |
| 103 | + }); |
| 104 | + } |
| 105 | + }, [ready]); |
| 106 | + |
| 107 | + return ( |
| 108 | + <div> |
| 109 | + <h1>Master Counter</h1> |
| 110 | + {peer?.id && <QRCode value={peer.id} />} |
| 111 | + |
| 112 | + <h2>Connected Remotes ({remotesList.length})</h2> |
| 113 | + <ul> |
| 114 | + {remotesList.map(remote => ( |
| 115 | + <li key={remote.id}> |
| 116 | + Remote {remote.id}: {remote.counter} |
| 117 | + </li> |
| 118 | + ))} |
| 119 | + </ul> |
| 120 | + |
| 121 | + <h2>Total: {remotesList.reduce((sum, remote) => sum + remote.counter, 0)}</h2> |
| 122 | + </div> |
| 123 | + ); |
| 124 | +} |
| 125 | +``` |
| 126 | +
|
| 127 | +### 3. Remote Component Implementation |
| 128 | +The library does provide: |
| 129 | +- WebRTC connection to master |
| 130 | +- Real-time data transmission |
| 131 | +- Connection state management |
| 132 | +- Automatic reconnection handling |
| 133 | +
|
| 134 | +You should implement: |
| 135 | +- UI with + and - buttons |
| 136 | +- Counter command sending logic |
| 137 | +- Remote device identification |
| 138 | +- Connection status display |
| 139 | +- Error handling specific to counter operations |
| 140 | +
|
| 141 | +Here's a minimal Remote component: |
| 142 | +```jsx |
| 143 | +function Remote() { |
| 144 | + const { ready, api } = usePeer(); |
| 145 | + |
| 146 | + const increment = () => { |
| 147 | + if (ready) { |
| 148 | + api.send({ type: "COUNTER_INCREMENT" }); |
| 149 | + } |
| 150 | + }; |
| 151 | + |
| 152 | + return ( |
| 153 | + <div> |
| 154 | + <h1>Remote Control</h1> |
| 155 | + <button onClick={increment}>+</button> |
| 156 | + </div> |
| 157 | + ); |
| 158 | +} |
| 159 | +``` |
| 160 | +
|
| 161 | +## Best Practices |
| 162 | +You should: |
| 163 | +- Use the `usePeer` hook for all WebRTC operations |
| 164 | +- Implement proper error handling, using the `humanizeError` function |
| 165 | +- Clean up connections in useEffect |
| 166 | +- Make sure your application correctly behaves in reconnection scenarios |
| 167 | +
|
| 168 | +## Technical Requirements |
| 169 | +The library does: |
| 170 | +- Handle WebRTC signaling through PeerJS |
| 171 | +- Manage real-time bidirectional communication |
| 172 | +- Maintain persistent connections |
| 173 | +- Handles connection errors |
| 174 | +- Handles reconnection scenarios |
| 175 | +- Provide React hooks for state management |
0 commit comments