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.
- package/dist/connection-manager.js +3 -2
- package/dist/index.js +45 -4
- package/package.json +1 -1
|
@@ -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
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
}
|