@liveblocks/react 0.18.1 → 0.18.3

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/index.d.ts CHANGED
@@ -32,6 +32,21 @@ declare type RoomProviderProps<TPresence extends JsonObject, TStorage extends Ls
32
32
  */
33
33
  id: string;
34
34
  children: React.ReactNode;
35
+ /**
36
+ * If you're on React 17 or lower, pass in a reference to
37
+ * `ReactDOM.unstable_batchedUpdates` or
38
+ * `ReactNative.unstable_batchedUpdates` here.
39
+ *
40
+ * @example
41
+ * import { unstable_batchedUpdates } from "react-dom";
42
+ *
43
+ * <RoomProvider ... unstable_batchedUpdates={unstable_batchedUpdates} />
44
+ *
45
+ * This will prevent you from running into the so-called "stale props"
46
+ * and/or "zombie child" problem that React 17 and lower can suffer from.
47
+ * Not necessary when you're on React v18 or later.
48
+ */
49
+ unstable_batchedUpdates?: (cb: () => void) => void;
35
50
  } & RoomInitializers<TPresence, TStorage>>;
36
51
  /**
37
52
  * For any function type, returns a similar function type, but without the
@@ -318,16 +333,6 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
318
333
  * );
319
334
  */
320
335
  useOthersMapped<T>(itemSelector: (other: User<TPresence, TUserMeta>) => T, itemIsEqual?: (prev: T, curr: T) => boolean): ReadonlyArray<readonly [connectionId: number, data: T]>;
321
- /**
322
- * Given a connection ID (as obtained by using `useOthersConnectionIds`), you can
323
- * call this selector deep down in your component stack to only have the
324
- * component re-render if properties for this particular user change.
325
- *
326
- * @example
327
- * // Returns full user and re-renders whenever anything on the user changes
328
- * const secondUser = useOther(2);
329
- */
330
- useOther(connectionId: number): User<TPresence, TUserMeta>;
331
336
  /**
332
337
  * Given a connection ID (as obtained by using `useOthersConnectionIds`), you
333
338
  * can call this selector deep down in your component stack to only have the
@@ -635,17 +640,6 @@ declare type RoomContextBundle<TPresence extends JsonObject, TStorage extends Ls
635
640
  * );
636
641
  */
637
642
  useOthersMapped<T>(itemSelector: (other: User<TPresence, TUserMeta>) => T, itemIsEqual?: (prev: T, curr: T) => boolean): ReadonlyArray<readonly [connectionId: number, data: T]>;
638
- /**
639
- * Given a connection ID (as obtained by using `useOthersConnectionIds`),
640
- * you can call this selector deep down in your component stack to only
641
- * have the component re-render if properties for this particular user
642
- * change.
643
- *
644
- * @example
645
- * // Returns full user and re-renders whenever anything on the user changes
646
- * const secondUser = useOther(2);
647
- */
648
- useOther(connectionId: number): User<TPresence, TUserMeta>;
649
643
  /**
650
644
  * Given a connection ID (as obtained by using `useOthersConnectionIds`),
651
645
  * you can call this selector deep down in your component stack to only
package/index.js CHANGED
@@ -12,6 +12,10 @@ function ClientSideSuspense(props) {
12
12
 
13
13
  // src/factory.tsx
14
14
  var _client = require('@liveblocks/client');
15
+
16
+
17
+
18
+
15
19
  var _internal = require('@liveblocks/client/internal');
16
20
 
17
21
  var _withselector = require('use-sync-external-store/shim/with-selector');
@@ -33,8 +37,20 @@ function useInitial(value) {
33
37
  var noop = () => {
34
38
  };
35
39
  var identity = (x) => x;
36
- function useSyncExternalStore(s, g, gg) {
37
- return _withselector.useSyncExternalStoreWithSelector.call(void 0, s, g, gg, identity);
40
+ var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\u2019re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you\u2019re ready to upgrade to React 18:
41
+
42
+ import { unstable_batchedUpdates } from "react-dom"; // or "react-native"
43
+
44
+ <RoomProvider id=${JSON.stringify(
45
+ roomId
46
+ )} ... unstable_batchedUpdates={unstable_batchedUpdates}>
47
+ ...
48
+ </RoomProvider>
49
+
50
+ Why? Please see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child for more information`;
51
+ var superfluous_unstable_batchedUpdates = "You don\u2019t need to pass unstable_batchedUpdates to RoomProvider anymore, since you\u2019re on React 18+ already.";
52
+ function useSyncExternalStore(s, gs, gss) {
53
+ return _withselector.useSyncExternalStoreWithSelector.call(void 0, s, gs, gss, identity);
38
54
  }
39
55
  var EMPTY_OTHERS = _internal.asArrayWithLegacyMethods.call(void 0, []);
40
56
  function getEmptyOthers() {
@@ -70,7 +86,12 @@ function makeMutationContext(room) {
70
86
  function createRoomContext(client) {
71
87
  const RoomContext = React2.createContext(null);
72
88
  function RoomProvider(props) {
73
- const { id: roomId, initialPresence, initialStorage } = props;
89
+ const {
90
+ id: roomId,
91
+ initialPresence,
92
+ initialStorage,
93
+ unstable_batchedUpdates
94
+ } = props;
74
95
  if (process.env.NODE_ENV !== "production") {
75
96
  if (!roomId) {
76
97
  throw new Error(
@@ -80,15 +101,27 @@ function createRoomContext(client) {
80
101
  if (typeof roomId !== "string") {
81
102
  throw new Error("RoomProvider id property should be a string.");
82
103
  }
104
+ const majorReactVersion = parseInt(React2.version) || 1;
105
+ const oldReactVersion = majorReactVersion < 18;
106
+ _internal.errorIf.call(void 0,
107
+ oldReactVersion && props.unstable_batchedUpdates === void 0,
108
+ missing_unstable_batchedUpdates(majorReactVersion, roomId)
109
+ );
110
+ _internal.deprecateIf.call(void 0,
111
+ !oldReactVersion && props.unstable_batchedUpdates !== void 0,
112
+ superfluous_unstable_batchedUpdates
113
+ );
83
114
  }
84
115
  const frozen = useInitial({
85
116
  initialPresence,
86
- initialStorage
117
+ initialStorage,
118
+ unstable_batchedUpdates
87
119
  });
88
120
  const [room, setRoom] = React2.useState(
89
121
  () => client.enter(roomId, {
90
- initialPresence,
91
- initialStorage,
122
+ initialPresence: frozen.initialPresence,
123
+ initialStorage: frozen.initialStorage,
124
+ unstable_batchedUpdates: frozen.unstable_batchedUpdates,
92
125
  DO_NOT_USE_withoutConnecting: typeof window === "undefined"
93
126
  })
94
127
  );
@@ -97,6 +130,7 @@ function createRoomContext(client) {
97
130
  client.enter(roomId, {
98
131
  initialPresence: frozen.initialPresence,
99
132
  initialStorage: frozen.initialStorage,
133
+ unstable_batchedUpdates: frozen.unstable_batchedUpdates,
100
134
  DO_NOT_USE_withoutConnecting: typeof window === "undefined"
101
135
  })
102
136
  );
@@ -164,50 +198,34 @@ function createRoomContext(client) {
164
198
  );
165
199
  return useOthers(wrappedSelector, wrappedIsEqual);
166
200
  }
167
- const sentinel = Symbol();
201
+ const NOT_FOUND = Symbol();
168
202
  function useOther(connectionId, selector, isEqual) {
169
- const _useCallback = React2.useCallback;
170
- const _useOthers = useOthers;
171
- if (selector === void 0) {
172
- const selector2 = _useCallback(
173
- (others) => others.find((other2) => other2.connectionId === connectionId),
174
- [connectionId]
175
- );
176
- const other = _useOthers(selector2, _client.shallow);
177
- if (other === void 0) {
178
- throw new Error(
179
- `No such other user with connection id ${connectionId} exists`
203
+ const wrappedSelector = React2.useCallback(
204
+ (others) => {
205
+ const other2 = others.find(
206
+ (other3) => other3.connectionId === connectionId
180
207
  );
181
- }
182
- return other;
183
- } else {
184
- const wrappedSelector = _useCallback(
185
- (others) => {
186
- const other2 = others.find(
187
- (other3) => other3.connectionId === connectionId
188
- );
189
- return other2 !== void 0 ? selector(other2) : sentinel;
190
- },
191
- [connectionId, selector]
192
- );
193
- const wrappedIsEqual = _useCallback(
194
- (prev, curr) => {
195
- if (prev === sentinel || curr === sentinel) {
196
- return prev === curr;
197
- }
198
- const eq = isEqual != null ? isEqual : Object.is;
199
- return eq(prev, curr);
200
- },
201
- [isEqual]
208
+ return other2 !== void 0 ? selector(other2) : NOT_FOUND;
209
+ },
210
+ [connectionId, selector]
211
+ );
212
+ const wrappedIsEqual = React2.useCallback(
213
+ (prev, curr) => {
214
+ if (prev === NOT_FOUND || curr === NOT_FOUND) {
215
+ return prev === curr;
216
+ }
217
+ const eq = isEqual != null ? isEqual : Object.is;
218
+ return eq(prev, curr);
219
+ },
220
+ [isEqual]
221
+ );
222
+ const other = useOthers(wrappedSelector, wrappedIsEqual);
223
+ if (other === NOT_FOUND) {
224
+ throw new Error(
225
+ `No such other user with connection id ${connectionId} exists`
202
226
  );
203
- const other = _useOthers(wrappedSelector, wrappedIsEqual);
204
- if (other === sentinel) {
205
- throw new Error(
206
- `No such other user with connection id ${connectionId} exists`
207
- );
208
- }
209
- return other;
210
227
  }
228
+ return other;
211
229
  }
212
230
  function useBroadcastEvent() {
213
231
  const room = useRoom();
@@ -443,11 +461,7 @@ function createRoomContext(client) {
443
461
  }
444
462
  function useOtherSuspense(connectionId, selector, isEqual) {
445
463
  useSuspendUntilPresenceLoaded();
446
- return useOther(
447
- connectionId,
448
- selector,
449
- isEqual
450
- );
464
+ return useOther(connectionId, selector, isEqual);
451
465
  }
452
466
  function useLegacyKeySuspense(key) {
453
467
  useSuspendUntilStorageLoaded();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/react",
3
- "version": "0.18.1",
3
+ "version": "0.18.3",
4
4
  "description": "A set of React hooks and providers to use Liveblocks declaratively.",
5
5
  "main": "./index.js",
6
6
  "module": "./index.mjs",
@@ -27,7 +27,7 @@
27
27
  "use-sync-external-store": "^1.2.0"
28
28
  },
29
29
  "peerDependencies": {
30
- "@liveblocks/client": "0.18.1",
30
+ "@liveblocks/client": "0.18.3",
31
31
  "react": "^16.14.0 || ^17 || ^18"
32
32
  },
33
33
  "repository": {
@@ -1 +0,0 @@
1
- ab4dc80c03188cfbc87c124cad9c824347a785b0