@automerge/automerge-repo-react-hooks 1.1.0 → 1.1.2

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/dist/index.js CHANGED
@@ -1,293 +1 @@
1
- import I, { createContext as H, useContext as j, useState as E, useRef as A, useEffect as _, useMemo as V } from "react";
2
- const $ = H(null);
3
- function L() {
4
- const e = j($);
5
- if (!e)
6
- throw new Error("Repo was not found on RepoContext.");
7
- return e;
8
- }
9
- function J(e) {
10
- const [a, s] = E(), f = L(), p = e ? f.find(e) : null, d = A(null);
11
- return _(() => {
12
- if (s(void 0), !p)
13
- return;
14
- d.current = p, p.doc().then((t) => {
15
- d.current === p && s(t);
16
- }).catch((t) => console.error(t));
17
- const l = (t) => s(t.doc);
18
- return p.on("change", l), () => {
19
- p.removeListener("change", l);
20
- };
21
- }, [p]), [a, (l, o) => {
22
- p && p.change(l, o);
23
- }];
24
- }
25
- const K = (e) => {
26
- const [a, s] = E({}), [f, p] = E({}), d = L();
27
- return _(
28
- () => {
29
- const v = (n, r) => {
30
- r && s((i) => ({ ...i, [n]: r }));
31
- }, l = (n) => {
32
- const r = n.documentId, i = ({ doc: h }) => v(r, h);
33
- n.on("change", i), p((h) => ({ ...h, [r]: i }));
34
- }, o = (n) => {
35
- d.find(n).off("change", f[n]), s((i) => {
36
- const { [n]: h, ...u } = i;
37
- return u;
38
- });
39
- };
40
- return e && (e.filter((i) => !a[i]).forEach((i) => {
41
- const h = d.find(i);
42
- h.doc().then((u) => {
43
- v(i, u), l(h);
44
- });
45
- }), Object.keys(a).map((i) => i).filter((i) => !e.includes(i)).forEach(o)), () => {
46
- Object.entries(f).forEach(([n, r]) => {
47
- d.find(n).off("change", r);
48
- });
49
- };
50
- },
51
- [e]
52
- // only run this effect when the list of ids changes
53
- ), a;
54
- }, F = (e, a = !1) => {
55
- history[a ? "pushState" : "replaceState"]("", "", "#" + e), window.dispatchEvent(
56
- new HashChangeEvent("hashchange", {
57
- newURL: window.location.origin + window.location.pathname + e,
58
- oldURL: window.location.href
59
- })
60
- );
61
- }, M = () => {
62
- const [e, a] = E(window.location.hash);
63
- return _(() => {
64
- const s = () => void a(window.location.hash);
65
- return window.addEventListener("hashchange", s), () => void window.removeEventListener("hashchange", s);
66
- }, []), e;
67
- }, C = (e, a) => new URLSearchParams(a.slice(1)).get(e), Q = (e, a, s) => {
68
- const f = new URLSearchParams(s.slice(1));
69
- return f.set(e, a), f.toString();
70
- }, q = (e, a) => e && (C(e, a) || localStorage.getItem(e)), B = (e, a) => {
71
- e && a !== C(e, window.location.hash) && F(Q(e, a, window.location.hash)), e && localStorage.setItem(e, a);
72
- }, W = ({
73
- key: e = "automergeUrl",
74
- onNoDocument: a = (f) => f.create(),
75
- onInvalidAutomergeUrl: s
76
- } = {}) => {
77
- const f = L(), p = M(), d = V(() => {
78
- const v = q(e, p);
79
- try {
80
- return v ? f.find(v) : a(f);
81
- } catch (l) {
82
- if (v && s)
83
- return s(f, l);
84
- throw l;
85
- }
86
- }, [p, f, a, s]);
87
- return _(() => {
88
- d && B(e, d.url);
89
- }, [p, d]), d;
90
- };
91
- function X(e) {
92
- const a = L(), [s, f] = E(
93
- e ? a.find(e) : void 0
94
- );
95
- return _(() => {
96
- f(e ? a.find(e) : void 0);
97
- }, [e]), s;
98
- }
99
- function O(e) {
100
- return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
101
- }
102
- var x = I, N = function(e) {
103
- return typeof e == "function";
104
- }, T = function(e) {
105
- var a = x.useState(e), s = a[0], f = a[1], p = x.useRef(s), d = x.useCallback(function(v) {
106
- p.current = N(v) ? v(p.current) : v, f(p.current);
107
- }, []);
108
- return [s, d, p];
109
- }, U = T;
110
- const S = /* @__PURE__ */ O(U);
111
- var P = { exports: {} };
112
- (function(e) {
113
- var a = Object.prototype.hasOwnProperty, s = "~";
114
- function f() {
115
- }
116
- Object.create && (f.prototype = /* @__PURE__ */ Object.create(null), new f().__proto__ || (s = !1));
117
- function p(o, t, n) {
118
- this.fn = o, this.context = t, this.once = n || !1;
119
- }
120
- function d(o, t, n, r, i) {
121
- if (typeof n != "function")
122
- throw new TypeError("The listener must be a function");
123
- var h = new p(n, r || o, i), u = s ? s + t : t;
124
- return o._events[u] ? o._events[u].fn ? o._events[u] = [o._events[u], h] : o._events[u].push(h) : (o._events[u] = h, o._eventsCount++), o;
125
- }
126
- function v(o, t) {
127
- --o._eventsCount === 0 ? o._events = new f() : delete o._events[t];
128
- }
129
- function l() {
130
- this._events = new f(), this._eventsCount = 0;
131
- }
132
- l.prototype.eventNames = function() {
133
- var t = [], n, r;
134
- if (this._eventsCount === 0)
135
- return t;
136
- for (r in n = this._events)
137
- a.call(n, r) && t.push(s ? r.slice(1) : r);
138
- return Object.getOwnPropertySymbols ? t.concat(Object.getOwnPropertySymbols(n)) : t;
139
- }, l.prototype.listeners = function(t) {
140
- var n = s ? s + t : t, r = this._events[n];
141
- if (!r)
142
- return [];
143
- if (r.fn)
144
- return [r.fn];
145
- for (var i = 0, h = r.length, u = new Array(h); i < h; i++)
146
- u[i] = r[i].fn;
147
- return u;
148
- }, l.prototype.listenerCount = function(t) {
149
- var n = s ? s + t : t, r = this._events[n];
150
- return r ? r.fn ? 1 : r.length : 0;
151
- }, l.prototype.emit = function(t, n, r, i, h, u) {
152
- var m = s ? s + t : t;
153
- if (!this._events[m])
154
- return !1;
155
- var c = this._events[m], g = arguments.length, y, w;
156
- if (c.fn) {
157
- switch (c.once && this.removeListener(t, c.fn, void 0, !0), g) {
158
- case 1:
159
- return c.fn.call(c.context), !0;
160
- case 2:
161
- return c.fn.call(c.context, n), !0;
162
- case 3:
163
- return c.fn.call(c.context, n, r), !0;
164
- case 4:
165
- return c.fn.call(c.context, n, r, i), !0;
166
- case 5:
167
- return c.fn.call(c.context, n, r, i, h), !0;
168
- case 6:
169
- return c.fn.call(c.context, n, r, i, h, u), !0;
170
- }
171
- for (w = 1, y = new Array(g - 1); w < g; w++)
172
- y[w - 1] = arguments[w];
173
- c.fn.apply(c.context, y);
174
- } else {
175
- var D = c.length, b;
176
- for (w = 0; w < D; w++)
177
- switch (c[w].once && this.removeListener(t, c[w].fn, void 0, !0), g) {
178
- case 1:
179
- c[w].fn.call(c[w].context);
180
- break;
181
- case 2:
182
- c[w].fn.call(c[w].context, n);
183
- break;
184
- case 3:
185
- c[w].fn.call(c[w].context, n, r);
186
- break;
187
- case 4:
188
- c[w].fn.call(c[w].context, n, r, i);
189
- break;
190
- default:
191
- if (!y)
192
- for (b = 1, y = new Array(g - 1); b < g; b++)
193
- y[b - 1] = arguments[b];
194
- c[w].fn.apply(c[w].context, y);
195
- }
196
- }
197
- return !0;
198
- }, l.prototype.on = function(t, n, r) {
199
- return d(this, t, n, r, !1);
200
- }, l.prototype.once = function(t, n, r) {
201
- return d(this, t, n, r, !0);
202
- }, l.prototype.removeListener = function(t, n, r, i) {
203
- var h = s ? s + t : t;
204
- if (!this._events[h])
205
- return this;
206
- if (!n)
207
- return v(this, h), this;
208
- var u = this._events[h];
209
- if (u.fn)
210
- u.fn === n && (!i || u.once) && (!r || u.context === r) && v(this, h);
211
- else {
212
- for (var m = 0, c = [], g = u.length; m < g; m++)
213
- (u[m].fn !== n || i && !u[m].once || r && u[m].context !== r) && c.push(u[m]);
214
- c.length ? this._events[h] = c.length === 1 ? c[0] : c : v(this, h);
215
- }
216
- return this;
217
- }, l.prototype.removeAllListeners = function(t) {
218
- var n;
219
- return t ? (n = s ? s + t : t, this._events[n] && v(this, n)) : (this._events = new f(), this._eventsCount = 0), this;
220
- }, l.prototype.off = l.prototype.removeListener, l.prototype.addListener = l.prototype.on, l.prefixed = s, l.EventEmitter = l, e.exports = l;
221
- })(P);
222
- var k = P.exports;
223
- const z = /* @__PURE__ */ O(k), R = new z(), Y = ({
224
- handle: e,
225
- localUserId: a,
226
- offlineTimeout: s = 3e4,
227
- getTime: f = () => (/* @__PURE__ */ new Date()).getTime()
228
- }) => {
229
- const [p, d, v] = S({}), [l, o, t] = S({});
230
- return _(() => {
231
- const n = (h) => {
232
- const [u, m] = h.message;
233
- u !== a && (t.current[u] || R.emit("new_peer", h), d({
234
- ...v.current,
235
- [u]: m
236
- }), o({
237
- ...t.current,
238
- [u]: f()
239
- }));
240
- }, r = () => {
241
- const h = v.current, u = t.current, m = f();
242
- for (const c in u)
243
- m - u[c] > s && (delete h[c], delete u[c]);
244
- d(h), o(u);
245
- };
246
- e.on("ephemeral-message", n);
247
- const i = setInterval(
248
- r,
249
- s
250
- );
251
- return () => {
252
- e.removeListener("ephemeral-message", n), clearInterval(i);
253
- };
254
- }, [e, a, s, f]), [p, l];
255
- }, Z = ({
256
- handle: e,
257
- userId: a,
258
- initialState: s,
259
- heartbeatTime: f = 15e3
260
- }) => {
261
- const [p, d, v] = S(s), l = (o) => {
262
- const t = typeof o == "function" ? o(v.current) : o;
263
- d(t), e.broadcast([a, t]);
264
- };
265
- return _(() => {
266
- const o = () => void e.broadcast([a, v.current]);
267
- o();
268
- const t = setInterval(o, f);
269
- return () => void clearInterval(t);
270
- }, [e, a, f]), _(() => {
271
- let o;
272
- const t = R.on("new_peer", () => {
273
- o = setTimeout(
274
- () => e.broadcast([a, v.current]),
275
- 500
276
- // Wait for the peer to be ready
277
- );
278
- });
279
- return () => {
280
- t.off("new_peer"), o && clearTimeout(o);
281
- };
282
- }, [e, a, R]), [p, l];
283
- };
284
- export {
285
- $ as RepoContext,
286
- W as useBootstrap,
287
- J as useDocument,
288
- K as useDocuments,
289
- X as useHandle,
290
- Z as useLocalAwareness,
291
- Y as useRemoteAwareness,
292
- L as useRepo
293
- };
1
+ import T,{createContext as k,useContext as A,useState as x,useRef as U,useEffect as g,useMemo as D}from"react";const O=k(null);function b(){const t=A(O);if(!t)throw new Error("Repo was not found on RepoContext.");return t}function P(t){const[s,o]=x(),i=b(),f=t?i.find(t):null,d=U(null);return g(()=>{if(o(void 0),!f)return;d.current=f,f.doc().then(a=>{d.current===f&&o(a)}).catch(a=>console.error(a));const u=a=>o(a.doc);return f.on("change",u),()=>{f.removeListener("change",u)}},[f]),[s,(u,a)=>{f&&f.change(u,a)}]}const H=t=>{const[s,o]=x({}),[i,f]=x({}),d=b();return g(()=>{const u=(e,r)=>{r&&o(l=>({...l,[e]:r}))},a=e=>{const r=e.documentId,l=({doc:v})=>u(r,v);e.on("change",l),f(v=>({...v,[r]:l}))},n=e=>{d.find(e).off("change",i[e]),o(r=>{const{[e]:l,...v}=r;return v})};return t&&(t.filter(e=>!s[e]).forEach(e=>{const r=d.find(e);r.doc().then(l=>{u(e,l),a(r)}).catch(l=>{console.error(`Error loading document ${e} in useDocuments: `,l)})}),Object.keys(s).map(e=>e).filter(e=>!t.includes(e)).forEach(n)),()=>{Object.entries(i).forEach(([e,r])=>{d.find(e).off("change",r)})}},[t]),s},M=(t,s=!1)=>{history[s?"pushState":"replaceState"]("","","#"+t),window.dispatchEvent(new HashChangeEvent("hashchange",{newURL:window.location.origin+window.location.pathname+t,oldURL:window.location.href}))},N=()=>{const[t,s]=x(window.location.hash);return g(()=>{const o=()=>void s(window.location.hash);return window.addEventListener("hashchange",o),()=>void window.removeEventListener("hashchange",o)},[]),t},S=(t,s)=>new URLSearchParams(s.slice(1)).get(t),B=(t,s,o)=>{const i=new URLSearchParams(o.slice(1));return i.set(t,s),i.toString()},$=(t,s)=>t&&(S(t,s)||localStorage.getItem(t)),q=(t,s)=>{t&&s!==S(t,window.location.hash)&&M(B(t,s,window.location.hash)),t&&localStorage.setItem(t,s)},z=({key:t="automergeUrl",onNoDocument:s=i=>i.create(),onInvalidAutomergeUrl:o}={})=>{const i=b(),f=N(),d=D(()=>{const u=$(t,f);try{return u?i.find(u):s(i)}catch(a){if(u&&o)return o(i,a);throw a}},[f,i,s,o]);return g(()=>{d&&q(t,d.url)},[f,d]),d};function F(t){const s=b(),[o,i]=x(t?s.find(t):void 0);return g(()=>{i(t?s.find(t):void 0)},[t]),o}function R(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var L=T,J=function(t){return typeof t=="function"},K=function(t){var s=L.useState(t),o=s[0],i=s[1],f=L.useRef(o),d=L.useCallback(function(u){f.current=J(u)?u(f.current):u,i(f.current)},[]);return[o,d,f]},Q=K;const E=R(Q);var I={exports:{}};(function(t){var s=Object.prototype.hasOwnProperty,o="~";function i(){}Object.create&&(i.prototype=Object.create(null),new i().__proto__||(o=!1));function f(n,e,r){this.fn=n,this.context=e,this.once=r||!1}function d(n,e,r,l,v){if(typeof r!="function")throw new TypeError("The listener must be a function");var p=new f(r,l||n,v),h=o?o+e:e;return n._events[h]?n._events[h].fn?n._events[h]=[n._events[h],p]:n._events[h].push(p):(n._events[h]=p,n._eventsCount++),n}function u(n,e){--n._eventsCount===0?n._events=new i:delete n._events[e]}function a(){this._events=new i,this._eventsCount=0}a.prototype.eventNames=function(){var n=[],e,r;if(this._eventsCount===0)return n;for(r in e=this._events)s.call(e,r)&&n.push(o?r.slice(1):r);return Object.getOwnPropertySymbols?n.concat(Object.getOwnPropertySymbols(e)):n},a.prototype.listeners=function(n){var e=o?o+n:n,r=this._events[e];if(!r)return[];if(r.fn)return[r.fn];for(var l=0,v=r.length,p=new Array(v);l<v;l++)p[l]=r[l].fn;return p},a.prototype.listenerCount=function(n){var e=o?o+n:n,r=this._events[e];return r?r.fn?1:r.length:0},a.prototype.emit=function(n,e,r,l,v,p){var h=o?o+n:n;if(!this._events[h])return!1;var c=this._events[h],m=arguments.length,y,w;if(c.fn){switch(c.once&&this.removeListener(n,c.fn,void 0,!0),m){case 1:return c.fn.call(c.context),!0;case 2:return c.fn.call(c.context,e),!0;case 3:return c.fn.call(c.context,e,r),!0;case 4:return c.fn.call(c.context,e,r,l),!0;case 5:return c.fn.call(c.context,e,r,l,v),!0;case 6:return c.fn.call(c.context,e,r,l,v,p),!0}for(w=1,y=new Array(m-1);w<m;w++)y[w-1]=arguments[w];c.fn.apply(c.context,y)}else{var j=c.length,_;for(w=0;w<j;w++)switch(c[w].once&&this.removeListener(n,c[w].fn,void 0,!0),m){case 1:c[w].fn.call(c[w].context);break;case 2:c[w].fn.call(c[w].context,e);break;case 3:c[w].fn.call(c[w].context,e,r);break;case 4:c[w].fn.call(c[w].context,e,r,l);break;default:if(!y)for(_=1,y=new Array(m-1);_<m;_++)y[_-1]=arguments[_];c[w].fn.apply(c[w].context,y)}}return!0},a.prototype.on=function(n,e,r){return d(this,n,e,r,!1)},a.prototype.once=function(n,e,r){return d(this,n,e,r,!0)},a.prototype.removeListener=function(n,e,r,l){var v=o?o+n:n;if(!this._events[v])return this;if(!e)return u(this,v),this;var p=this._events[v];if(p.fn)p.fn===e&&(!l||p.once)&&(!r||p.context===r)&&u(this,v);else{for(var h=0,c=[],m=p.length;h<m;h++)(p[h].fn!==e||l&&!p[h].once||r&&p[h].context!==r)&&c.push(p[h]);c.length?this._events[v]=c.length===1?c[0]:c:u(this,v)}return this},a.prototype.removeAllListeners=function(n){var e;return n?(e=o?o+n:n,this._events[e]&&u(this,e)):(this._events=new i,this._eventsCount=0),this},a.prototype.off=a.prototype.removeListener,a.prototype.addListener=a.prototype.on,a.prefixed=o,a.EventEmitter=a,t.exports=a})(I);var V=I.exports;const W=R(V),C=new W,X=({handle:t,localUserId:s,offlineTimeout:o=3e4,getTime:i=()=>new Date().getTime()})=>{const[f,d,u]=E({}),[a,n,e]=E({});return g(()=>{const r=p=>{const[h,c]=p.message;h!==s&&(e.current[h]||C.emit("new_peer",p),d({...u.current,[h]:c}),n({...e.current,[h]:i()}))},l=()=>{const p=u.current,h=e.current,c=i();for(const m in h)c-h[m]>o&&(delete p[m],delete h[m]);d(p),n(h)};t.on("ephemeral-message",r);const v=setInterval(l,o);return()=>{t.removeListener("ephemeral-message",r),clearInterval(v)}},[t,s,o,i]),[f,a]},Y=({handle:t,userId:s,initialState:o,heartbeatTime:i=15e3})=>{const[f,d,u]=E(o),a=n=>{const e=typeof n=="function"?n(u.current):n;d(e),t.broadcast([s,e])};return g(()=>{if(!s)return;const n=()=>void t.broadcast([s,u.current]);n();const e=setInterval(n,i);return()=>void clearInterval(e)},[t,s,i]),g(()=>{let n;const e=C.on("new_peer",()=>{n=setTimeout(()=>t.broadcast([s,u.current]),500)});return()=>{e.off("new_peer"),n&&clearTimeout(n)}},[t,s,C]),[f,a]};export{O as RepoContext,z as useBootstrap,P as useDocument,H as useDocuments,F as useHandle,Y as useLocalAwareness,X as useRemoteAwareness,b as useRepo};
@@ -1 +1 @@
1
- {"version":3,"file":"useDocuments.d.ts","sourceRoot":"","sources":["../src/useDocuments.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAGZ,UAAU,EACX,MAAM,2BAA2B,CAAA;AAIlC;;;GAGG;AACH,eAAO,MAAM,YAAY,YAAa,KAAK,EAAE,qBAmE5C,CAAA;AAED,KAAK,KAAK,GAAG,UAAU,GAAG,YAAY,CAAA"}
1
+ {"version":3,"file":"useDocuments.d.ts","sourceRoot":"","sources":["../src/useDocuments.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAGZ,UAAU,EACX,MAAM,2BAA2B,CAAA;AAIlC;;;GAGG;AACH,eAAO,MAAM,YAAY,YAAa,KAAK,EAAE,qBAqE5C,CAAA;AAED,KAAK,KAAK,GAAG,UAAU,GAAG,YAAY,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useLocalAwareness.d.ts","sourceRoot":"","sources":["../src/useLocalAwareness.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAErD,MAAM,WAAW,sBAAsB;IACrC,qDAAqD;IACrD,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;IAC1B,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,YAAY,EAAE,GAAG,CAAA;IACjB,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AACD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,qDAK3B,sBAAsB,UA6CxB,CAAA"}
1
+ {"version":3,"file":"useLocalAwareness.d.ts","sourceRoot":"","sources":["../src/useLocalAwareness.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAErD,MAAM,WAAW,sBAAsB;IACrC,qDAAqD;IACrD,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;IAC1B,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,YAAY,EAAE,GAAG,CAAA;IACjB,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AACD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,qDAK3B,sBAAsB,UAmDxB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automerge/automerge-repo-react-hooks",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Hooks to access an Automerge Repo from your react app.",
5
5
  "repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo-react-hooks",
6
6
  "author": "Peter van Hardenberg <pvh@pvh.ca>",
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@automerge/automerge": "^2.1.9",
18
- "@automerge/automerge-repo": "1.1.0",
18
+ "@automerge/automerge-repo": "1.1.2",
19
19
  "eventemitter3": "^5.0.1",
20
20
  "react": "^18.2.0",
21
21
  "react-dom": "^18.2.0",
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "e9e7d3f27ec2ac8a2e9d122ece80598918940067"
45
+ "gitHead": "8bcba031ae952b1f3302cd41d1066cd2db5b677f"
46
46
  }
@@ -54,6 +54,8 @@ export const useDocuments = <T>(ids?: DocId[]) => {
54
54
  handle.doc().then(doc => {
55
55
  updateDocument(id, doc)
56
56
  addListener(handle)
57
+ }).catch(err => {
58
+ console.error(`Error loading document ${id} in useDocuments: `, err)
57
59
  })
58
60
  })
59
61
 
@@ -47,6 +47,12 @@ export const useLocalAwareness = ({
47
47
  }
48
48
 
49
49
  useEffect(() => {
50
+ // Don't broadcast if userId isn't set: this avoids bogus broadcasts
51
+ // during the loading of a userId document.
52
+ if (!userId) {
53
+ return
54
+ }
55
+
50
56
  // Send periodic heartbeats
51
57
  const heartbeat = () =>
52
58
  void handle.broadcast([userId, localStateRef.current])