react-broadcast-sync 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/skills/react-broadcast-sync/SKILL.md +45 -15
package/llms.txt
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> React hook and provider for cross-tab messaging over BroadcastChannel, with helpers for manually syncing state between tabs (no automatic state replication).
|
|
4
4
|
|
|
5
|
-
Version 2.
|
|
5
|
+
Version 2.1.0. Install: `npm install react-broadcast-sync`. Same origin only. Generated from README.md by scripts/generate-llms-txt.mjs; do not edit by hand.
|
|
6
6
|
|
|
7
7
|
## Syncing Shared State (filters, settings)
|
|
8
8
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-broadcast-sync",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "React hook and provider for cross-tab messaging over BroadcastChannel, with helpers for manually syncing state between tabs (no automatic state replication).",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -52,25 +52,55 @@ Do NOT call `postMessage` from a `useEffect` that watches state which incoming m
|
|
|
52
52
|
|
|
53
53
|
## Recipe 2: give a late-opened tab the current state
|
|
54
54
|
|
|
55
|
-
Because there is no replay, a new tab must ask and an existing tab must answer.
|
|
55
|
+
Because there is no replay, a new tab must ask and an existing tab must answer. This complete counter component starts at zero if nobody answers. Open it in two tabs on the same origin, increment in one, then open another tab to see it request the current value.
|
|
56
56
|
|
|
57
57
|
```tsx
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
import { useEffect, useRef, useState } from 'react';
|
|
59
|
+
import { useBroadcastChannel } from 'react-broadcast-sync';
|
|
60
|
+
|
|
61
|
+
// Keep this list stable so postMessage stays stable across renders.
|
|
62
|
+
const immediateMessageTypes = ['count-update', 'state-request'];
|
|
63
|
+
|
|
64
|
+
export default function Counter() {
|
|
65
|
+
const [count, setCount] = useState(0);
|
|
66
|
+
const countRef = useRef(count);
|
|
67
|
+
|
|
68
|
+
const applyCount = (next: number) => {
|
|
69
|
+
countRef.current = next;
|
|
70
|
+
setCount(next);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const { postMessage } = useBroadcastChannel('counter', {
|
|
74
|
+
excludedBatchMessageTypes: immediateMessageTypes,
|
|
75
|
+
onMessage: {
|
|
76
|
+
'count-update': msg => applyCount(msg.message),
|
|
77
|
+
'state-request': () => postMessage('count-update', countRef.current),
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
postMessage('state-request', null);
|
|
83
|
+
}, [postMessage]);
|
|
84
|
+
|
|
85
|
+
const increment = () => {
|
|
86
|
+
const next = countRef.current + 1;
|
|
87
|
+
applyCount(next);
|
|
88
|
+
postMessage('count-update', next);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<button type="button" onClick={increment}>
|
|
93
|
+
Count: {count}
|
|
94
|
+
</button>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
71
97
|
```
|
|
72
98
|
|
|
73
|
-
|
|
99
|
+
The ref holds the latest applied value for replies and successive clicks, including before React renders again. Updates and requests are sent immediately in this demo. Incoming updates only apply state; they do not re-broadcast it.
|
|
100
|
+
|
|
101
|
+
**Consistency boundary:** this is an absolute-value demo for sequential edits, not an atomic multi-tab counter. Two tabs can both increment the same old value and overwrite each other's changes. The simple, unversioned request/response also has no stale-response or multi-responder handling: a delayed reply can overwrite a newer local edit, and several tabs can answer with different values. The last value received by each tab is applied; global ordering or convergence is not guaranteed. When that matters, design an application protocol with a `requestId`, a targeted reply (receiver checks the intended target), and revision/conflict rules. For atomic increments, use an authority that serializes operations or a suitable conflict-safe counter protocol; the hook does not provide one.
|
|
102
|
+
|
|
103
|
+
In development, React StrictMode re-runs mount effects, so two initialization requests and duplicate replies are expected. They are not a bug or a re-broadcast loop. In this example, applying the same count again is harmless, but duplicate initialization does not solve the consistency limits above.
|
|
74
104
|
|
|
75
105
|
## Recipe 3: latest value only
|
|
76
106
|
|