react-mirrorstate 0.3.1 → 0.4.0

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.
@@ -93,6 +93,8 @@ class WebSocketConnectionManager {
93
93
  }
94
94
  pendingUpdates = new Map();
95
95
  updateState(name, state) {
96
+ // Immediately update currentStates so subsequent reads get the latest value
97
+ this.currentStates.set(name, state);
96
98
  if (this.ws?.readyState !== WebSocket.OPEN) {
97
99
  this.queuedUpdates.set(name, state);
98
100
  return;
@@ -102,7 +104,7 @@ class WebSocketConnectionManager {
102
104
  if (pendingUpdate) {
103
105
  clearTimeout(pendingUpdate);
104
106
  }
105
- // Debounce rapid updates
107
+ // Debounce rapid WebSocket sends
106
108
  const timeout = setTimeout(() => {
107
109
  if (!this.ws) {
108
110
  return;
@@ -111,7 +113,6 @@ class WebSocketConnectionManager {
111
113
  name,
112
114
  state,
113
115
  }));
114
- this.currentStates.set(name, state);
115
116
  this.pendingUpdates.delete(name);
116
117
  }, 10);
117
118
  this.pendingUpdates.set(name, timeout);
package/dist/index.js CHANGED
@@ -2,6 +2,40 @@ import { useEffect, useState, useRef } from "react";
2
2
  import { produce } from "immer";
3
3
  import { connectionManager } from "./connection-manager";
4
4
  import { INITIAL_STATES } from "virtual:mirrorstate/initial-states";
5
+ // Batching state for each mirror state name
6
+ const batchQueues = new Map();
7
+ const batchPending = new Map();
8
+ const batchCallbacks = new Map();
9
+ function scheduleBatchFlush(name) {
10
+ if (batchPending.get(name)) {
11
+ return;
12
+ }
13
+ batchPending.set(name, true);
14
+ queueMicrotask(() => {
15
+ const queue = batchQueues.get(name);
16
+ const callbacks = batchCallbacks.get(name);
17
+ if (!queue || queue.length === 0) {
18
+ batchPending.set(name, false);
19
+ return;
20
+ }
21
+ // Apply all queued updates in sequence
22
+ // Get current state from connection manager, falling back to INITIAL_STATES
23
+ let currentState = connectionManager.getCurrentState(name) ??
24
+ INITIAL_STATES?.[name];
25
+ // Apply each update sequentially, handling both object mutations and primitive returns
26
+ let newState = currentState;
27
+ queue.forEach((updater) => {
28
+ newState = produce(newState, updater);
29
+ });
30
+ // Clear the queue
31
+ batchQueues.set(name, []);
32
+ batchPending.set(name, false);
33
+ // Update connection manager and notify all callbacks
34
+ connectionManager.updateState(name, newState);
35
+ callbacks?.forEach((callback) => callback(newState));
36
+ batchCallbacks.set(name, new Set());
37
+ });
38
+ }
5
39
  export function useMirrorState(name, initialValue) {
6
40
  // Capture initialValue once on first render to make it stable
7
41
  const initialValueRef = useRef(initialValue);
@@ -24,10 +58,17 @@ export function useMirrorState(name, initialValue) {
24
58
  };
25
59
  }, [name]);
26
60
  const updateMirrorState = (updater) => {
27
- const currentState = connectionManager.getCurrentState(name) ?? state;
28
- const newState = produce(currentState, updater);
29
- connectionManager.updateState(name, newState);
30
- setState(newState);
61
+ // Initialize batch queue for this name if needed
62
+ if (!batchQueues.has(name)) {
63
+ batchQueues.set(name, []);
64
+ batchCallbacks.set(name, new Set());
65
+ }
66
+ // Add updater to batch queue
67
+ batchQueues.get(name).push(updater);
68
+ // Add setState to callbacks
69
+ batchCallbacks.get(name).add(setState);
70
+ // Schedule batch flush
71
+ scheduleBatchFlush(name);
31
72
  };
32
73
  return [state, updateMirrorState];
33
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-mirrorstate",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "React library for bidirectional state synchronization with MirrorState",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",