@plq/use-persisted-state 1.4.2 → 1.4.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/README.md +3 -3
- package/lib/create-async-persisted-state.d.ts.map +1 -1
- package/lib/create-async-persisted-state.js +4 -39
- package/lib/create-async-persisted-state.js.map +1 -1
- package/lib/create-persisted-state.d.ts.map +1 -1
- package/lib/create-persisted-state.js +2 -37
- package/lib/create-persisted-state.js.map +1 -1
- package/lib/utils/use-storage-handler.d.ts +1 -4
- package/lib/utils/use-storage-handler.d.ts.map +1 -1
- package/lib/utils/use-storage-handler.js +4 -27
- package/lib/utils/use-storage-handler.js.map +1 -1
- package/package.json +1 -1
- package/src/create-async-persisted-state.ts +4 -8
- package/src/create-persisted-state.ts +2 -6
- package/src/utils/use-storage-handler.ts +2 -32
package/README.md
CHANGED
|
@@ -249,9 +249,9 @@ tells a `null` you stored apart from a `null` that JSON produced.
|
|
|
249
249
|
keeps `undefined` in memory, as `useState` would, and other components already mounted on that key
|
|
250
250
|
see no change and keep the value they hold. After a remount or a reload the key is absent, so the
|
|
251
251
|
initial value comes back.
|
|
252
|
-
- **`NaN`, `Infinity`, `-Infinity`** — these are written as `null`.
|
|
253
|
-
|
|
254
|
-
|
|
252
|
+
- **`NaN`, `Infinity`, `-Infinity`** — these are written as `null`. A storage change reported by the
|
|
253
|
+
backend applies that `null` to every listening component, including the writer. Any reader after
|
|
254
|
+
a reload also reads back `null`.
|
|
255
255
|
|
|
256
256
|
## Contributing
|
|
257
257
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-async-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAEtE,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,CAAC,SAAS,YAAY,EACtE,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,GACT,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"create-async-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAEtE,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,CAAC,SAAS,YAAY,EACtE,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,GACT,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAmGvC"}
|
|
@@ -1,44 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
38
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
6
|
exports.default = createAsyncPersistedState;
|
|
40
7
|
const react_1 = require("react");
|
|
41
|
-
const use_storage_handler_1 =
|
|
8
|
+
const use_storage_handler_1 = __importDefault(require("./utils/use-storage-handler"));
|
|
42
9
|
const get_new_value_1 = __importDefault(require("./utils/get-new-value"));
|
|
43
10
|
const get_new_item_1 = __importDefault(require("./utils/get-new-item"));
|
|
44
11
|
const get_persisted_value_1 = __importDefault(require("./utils/get-persisted-value"));
|
|
@@ -52,7 +19,7 @@ function createAsyncPersistedState(storageKey, storage) {
|
|
|
52
19
|
entryWrites = removal.catch(() => undefined);
|
|
53
20
|
return removal;
|
|
54
21
|
};
|
|
55
|
-
const commitEntry = (key, newValue
|
|
22
|
+
const commitEntry = (key, newValue) => {
|
|
56
23
|
const write = entryWrites.then(async () => {
|
|
57
24
|
const persistedItem = await storage.get(safeStorageKey);
|
|
58
25
|
let newItem;
|
|
@@ -63,7 +30,6 @@ function createAsyncPersistedState(storageKey, storage) {
|
|
|
63
30
|
// A write replaces the whole entry, so an unreadable one is skipped rather than rebuilt without other keys.
|
|
64
31
|
return;
|
|
65
32
|
}
|
|
66
|
-
(0, use_storage_handler_1.recordOwnWrite)(pendingOwnWrites, newItem);
|
|
67
33
|
await storage.set({ [safeStorageKey]: newItem });
|
|
68
34
|
});
|
|
69
35
|
// The chain must outlive a failed write; the rejection still reaches the caller through `write`.
|
|
@@ -81,16 +47,15 @@ function createAsyncPersistedState(storageKey, storage) {
|
|
|
81
47
|
hasAppliedValue.current = true;
|
|
82
48
|
setState(value);
|
|
83
49
|
}, []);
|
|
84
|
-
const pendingOwnWrites = (0, react_1.useRef)([]);
|
|
85
50
|
const setPersistedState = (0, react_1.useCallback)(async (newState) => {
|
|
86
51
|
const newValue = (0, get_new_value_1.default)(newState, latestValue.current);
|
|
87
52
|
applyValue(newValue);
|
|
88
|
-
await commitEntry(key, newValue
|
|
53
|
+
await commitEntry(key, newValue);
|
|
89
54
|
}, [key, applyValue]);
|
|
90
55
|
// The first render's initial value: reloading on a later identity would re-run the effect forever.
|
|
91
56
|
const mountInitialValue = (0, react_1.useRef)(initialValue);
|
|
92
57
|
// Subscribed before the load: effects run in declaration order, and reading first would lose writes in between.
|
|
93
|
-
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue
|
|
58
|
+
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue);
|
|
94
59
|
(0, react_1.useEffect)(() => {
|
|
95
60
|
// Separate from `hasAppliedValue`: only this closure knows whether its own load is still current.
|
|
96
61
|
let isCancelled = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-async-persisted-state.js","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-async-persisted-state.js","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAOtE,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"create-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAOtE,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,CA0D/G"}
|
|
@@ -1,44 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
38
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
6
|
exports.default = createPersistedState;
|
|
40
7
|
const react_1 = require("react");
|
|
41
|
-
const use_storage_handler_1 =
|
|
8
|
+
const use_storage_handler_1 = __importDefault(require("./utils/use-storage-handler"));
|
|
42
9
|
const get_new_value_1 = __importDefault(require("./utils/get-new-value"));
|
|
43
10
|
const get_new_item_1 = __importDefault(require("./utils/get-new-item"));
|
|
44
11
|
const get_persisted_value_1 = __importDefault(require("./utils/get-persisted-value"));
|
|
@@ -63,7 +30,6 @@ function createPersistedState(storageKey, storage) {
|
|
|
63
30
|
renderedKey.current = key;
|
|
64
31
|
applyValue(readPersisted(key, initialValue));
|
|
65
32
|
}
|
|
66
|
-
const pendingOwnWrites = (0, react_1.useRef)([]);
|
|
67
33
|
const setPersistedState = (0, react_1.useCallback)((newState) => {
|
|
68
34
|
const newValue = (0, get_new_value_1.default)(newState, latestValue.current);
|
|
69
35
|
applyValue(newValue);
|
|
@@ -76,10 +42,9 @@ function createPersistedState(storageKey, storage) {
|
|
|
76
42
|
// A write replaces the whole entry, so an unreadable one is skipped rather than rebuilt without other keys.
|
|
77
43
|
return;
|
|
78
44
|
}
|
|
79
|
-
(0, use_storage_handler_1.recordOwnWrite)(pendingOwnWrites, newItem);
|
|
80
45
|
storage.set({ [safeStorageKey]: newItem });
|
|
81
46
|
}, [key, applyValue]);
|
|
82
|
-
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue
|
|
47
|
+
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue);
|
|
83
48
|
return [state, setPersistedState];
|
|
84
49
|
};
|
|
85
50
|
return [usePersistedState, clear];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-persisted-state.js","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-persisted-state.js","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":";;;;;AAWA,uCA0DC;AApED,iCAAqD;AAKrD,sFAA2D;AAC3D,0EAA+C;AAC/C,wEAA6C;AAC7C,sFAA2D;AAE3D,SAAwB,oBAAoB,CAAC,UAAkB,EAAE,OAAgB;IAC/E,MAAM,cAAc,GAAG,wBAAwB,UAAU,EAAE,CAAA;IAC3D,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IAChC,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,CAAI,GAAW,EAAE,YAAe,EAAK,EAAE,CAC3D,IAAA,6BAAiB,EAAI,GAAG,EAAE,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,CAAC,CAAA;IAEtF,MAAM,iBAAiB,GAAG,CAAI,GAAW,EAAE,YAAe,EAAwB,EAAE;QAClF,wGAAwG;QACxG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAI,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAA;QAE7E,2FAA2F;QAC3F,MAAM,WAAW,GAAG,IAAA,cAAM,EAAC,KAAK,CAAC,CAAA;QAEjC,MAAM,UAAU,GAAG,IAAA,mBAAW,EAAC,CAAC,KAAQ,EAAQ,EAAE;YAChD,WAAW,CAAC,OAAO,GAAG,KAAK,CAAA;YAE3B,QAAQ,CAAC,KAAK,CAAC,CAAA;QACjB,CAAC,EAAE,EAAE,CAAC,CAAA;QAEN,6GAA6G;QAC7G,MAAM,WAAW,GAAG,IAAA,cAAM,EAAC,GAAG,CAAC,CAAA;QAE/B,IAAI,WAAW,CAAC,OAAO,KAAK,GAAG,EAAE,CAAC;YAChC,WAAW,CAAC,OAAO,GAAG,GAAG,CAAA;YAEzB,UAAU,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAA;QAC9C,CAAC;QAED,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EACnC,CAAC,QAAiC,EAAQ,EAAE;YAC1C,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAAI,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;YAE9D,UAAU,CAAC,QAAQ,CAAC,CAAA;YAEpB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,CAAA;YACjE,IAAI,OAAe,CAAA;YAEnB,IAAI,CAAC;gBACH,OAAO,GAAG,IAAA,sBAAU,EAAI,GAAG,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAA;YACvD,CAAC;YAAC,MAAM,CAAC;gBACP,4GAA4G;gBAC5G,OAAM;YACR,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;QAC5C,CAAC,EACD,CAAC,GAAG,EAAE,UAAU,CAAC,CAClB,CAAA;QAED,IAAA,6BAAiB,EAAI,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;QAE5E,OAAO,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAA;IACnC,CAAC,CAAA;IAED,OAAO,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAA;AACnC,CAAC"}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import type React from 'react';
|
|
2
1
|
import type { AsyncStorage, Storage } from '../@types/storage';
|
|
3
|
-
|
|
4
|
-
export declare function recordOwnWrite(pendingOwnWrites: React.RefObject<string[]>, item: string): void;
|
|
5
|
-
export default function useStorageHandler<T>(key: string, storageKey: string, applyValue: (value: T) => void, storage: AsyncStorage | Storage, initialValue: T | (() => T), pendingOwnWrites: React.RefObject<string[]>): void;
|
|
2
|
+
export default function useStorageHandler<T>(key: string, storageKey: string, applyValue: (value: T) => void, storage: AsyncStorage | Storage, initialValue: T | (() => T)): void;
|
|
6
3
|
//# sourceMappingURL=use-storage-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-storage-handler.d.ts","sourceRoot":"","sources":["../../src/utils/use-storage-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-storage-handler.d.ts","sourceRoot":"","sources":["../../src/utils/use-storage-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAiB,MAAM,mBAAmB,CAAA;AAgE7E,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,CAAC,EACzC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC9B,OAAO,EAAE,YAAY,GAAG,OAAO,EAC/B,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAC1B,IAAI,CAiBN"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.recordOwnWrite = recordOwnWrite;
|
|
4
3
|
exports.default = useStorageHandler;
|
|
5
4
|
const react_1 = require("react");
|
|
6
5
|
const is_1 = require("@plq/is");
|
|
@@ -30,55 +29,33 @@ function applyRemoval(change, itemKey, applyValue, latestInitialValue) {
|
|
|
30
29
|
return;
|
|
31
30
|
applyValue(initialValue);
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
// Capped, because a backend that never reports back leaves every record unmatched.
|
|
35
|
-
const MAX_PENDING_OWN_WRITES = 8;
|
|
36
|
-
/** Records an entry before it is written, because a backend may report the change before the write settles. */
|
|
37
|
-
function recordOwnWrite(pendingOwnWrites, item) {
|
|
38
|
-
const pending = pendingOwnWrites.current;
|
|
39
|
-
if (pending.length >= MAX_PENDING_OWN_WRITES)
|
|
40
|
-
pending.shift();
|
|
41
|
-
pending.push(item);
|
|
42
|
-
}
|
|
43
|
-
// Applying a hook's own echo would re-decode the entry and re-render for a value it already holds.
|
|
44
|
-
function consumeOwnWriteEcho(entry, pendingOwnWrites) {
|
|
45
|
-
const matched = pendingOwnWrites.current.indexOf(entry);
|
|
46
|
-
if (matched === -1)
|
|
47
|
-
return false;
|
|
48
|
-
// A backend reports writes in the order it took them, so a record still unmatched has no echo left.
|
|
49
|
-
pendingOwnWrites.current.splice(0, matched + 1);
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
function createStorageHandler(itemKey, storageKey, applyValue, latestInitialValue, pendingOwnWrites) {
|
|
32
|
+
function createStorageHandler(itemKey, storageKey, applyValue, latestInitialValue) {
|
|
53
33
|
return (changes) => {
|
|
54
34
|
for (const [key, change] of Object.entries(changes)) {
|
|
55
35
|
if (key !== storageKey)
|
|
56
36
|
continue;
|
|
57
|
-
// Ahead of the echo check, which needs an entry to match and a removal has none.
|
|
58
37
|
if (change.newValue === null || change.newValue === undefined) {
|
|
59
38
|
applyRemoval(change, itemKey, applyValue, latestInitialValue);
|
|
60
39
|
continue;
|
|
61
40
|
}
|
|
62
|
-
if (consumeOwnWriteEcho(change.newValue, pendingOwnWrites))
|
|
63
|
-
continue;
|
|
64
41
|
const newValue = readStoredValue(itemKey, change.newValue);
|
|
65
42
|
if (newValue.status === 'stored')
|
|
66
43
|
applyValue(newValue.value);
|
|
67
44
|
}
|
|
68
45
|
};
|
|
69
46
|
}
|
|
70
|
-
function useStorageHandler(key, storageKey, applyValue, storage, initialValue
|
|
47
|
+
function useStorageHandler(key, storageKey, applyValue, storage, initialValue) {
|
|
71
48
|
// A ref, not a dependency: an inline initial value changes identity every render and would churn it.
|
|
72
49
|
const latestInitialValue = (0, react_1.useRef)(initialValue);
|
|
73
50
|
latestInitialValue.current = initialValue;
|
|
74
51
|
(0, react_1.useEffect)(() => {
|
|
75
|
-
const handleStorage = createStorageHandler(key, storageKey, applyValue, latestInitialValue
|
|
52
|
+
const handleStorage = createStorageHandler(key, storageKey, applyValue, latestInitialValue);
|
|
76
53
|
storage.onChanged.addListener(handleStorage);
|
|
77
54
|
return () => {
|
|
78
55
|
if (storage.onChanged.hasListener(handleStorage)) {
|
|
79
56
|
storage.onChanged.removeListener(handleStorage);
|
|
80
57
|
}
|
|
81
58
|
};
|
|
82
|
-
}, [key, storage.onChanged, storageKey, applyValue
|
|
59
|
+
}, [key, storage.onChanged, storageKey, applyValue]);
|
|
83
60
|
}
|
|
84
61
|
//# sourceMappingURL=use-storage-handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-storage-handler.js","sourceRoot":"","sources":["../../src/utils/use-storage-handler.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"use-storage-handler.js","sourceRoot":"","sources":["../../src/utils/use-storage-handler.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type React from 'react'
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
3
3
|
|
|
4
|
-
import useStorageHandler
|
|
4
|
+
import useStorageHandler from './utils/use-storage-handler'
|
|
5
5
|
import getNewValue from './utils/get-new-value'
|
|
6
6
|
import getNewItem from './utils/get-new-item'
|
|
7
7
|
import getPersistedValue from './utils/get-persisted-value'
|
|
@@ -27,7 +27,7 @@ export default function createAsyncPersistedState<S extends AsyncStorage>(
|
|
|
27
27
|
return removal
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const commitEntry = <T>(key: string, newValue: T
|
|
30
|
+
const commitEntry = <T>(key: string, newValue: T): Promise<void> => {
|
|
31
31
|
const write = entryWrites.then(async () => {
|
|
32
32
|
const persistedItem = await storage.get(safeStorageKey)
|
|
33
33
|
let newItem: string
|
|
@@ -39,8 +39,6 @@ export default function createAsyncPersistedState<S extends AsyncStorage>(
|
|
|
39
39
|
return
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
recordOwnWrite(pendingOwnWrites, newItem)
|
|
43
|
-
|
|
44
42
|
await storage.set({ [safeStorageKey]: newItem })
|
|
45
43
|
})
|
|
46
44
|
|
|
@@ -66,15 +64,13 @@ export default function createAsyncPersistedState<S extends AsyncStorage>(
|
|
|
66
64
|
setState(value)
|
|
67
65
|
}, [])
|
|
68
66
|
|
|
69
|
-
const pendingOwnWrites = useRef<string[]>([])
|
|
70
|
-
|
|
71
67
|
const setPersistedState = useCallback(
|
|
72
68
|
async (newState: React.SetStateAction<T>): Promise<void> => {
|
|
73
69
|
const newValue = getNewValue<T>(newState, latestValue.current)
|
|
74
70
|
|
|
75
71
|
applyValue(newValue)
|
|
76
72
|
|
|
77
|
-
await commitEntry<T>(key, newValue
|
|
73
|
+
await commitEntry<T>(key, newValue)
|
|
78
74
|
},
|
|
79
75
|
[key, applyValue],
|
|
80
76
|
)
|
|
@@ -83,7 +79,7 @@ export default function createAsyncPersistedState<S extends AsyncStorage>(
|
|
|
83
79
|
const mountInitialValue = useRef(initialValue)
|
|
84
80
|
|
|
85
81
|
// Subscribed before the load: effects run in declaration order, and reading first would lose writes in between.
|
|
86
|
-
useStorageHandler<T>(key, safeStorageKey, applyValue, storage, initialValue
|
|
82
|
+
useStorageHandler<T>(key, safeStorageKey, applyValue, storage, initialValue)
|
|
87
83
|
|
|
88
84
|
useEffect(() => {
|
|
89
85
|
// Separate from `hasAppliedValue`: only this closure knows whether its own load is still current.
|
|
@@ -4,7 +4,7 @@ import { useCallback, useRef, useState } from 'react'
|
|
|
4
4
|
import type { Storage } from './@types/storage'
|
|
5
5
|
import type { PersistedState, UsePersistedState } from './@types/hook'
|
|
6
6
|
|
|
7
|
-
import useStorageHandler
|
|
7
|
+
import useStorageHandler from './utils/use-storage-handler'
|
|
8
8
|
import getNewValue from './utils/get-new-value'
|
|
9
9
|
import getNewItem from './utils/get-new-item'
|
|
10
10
|
import getPersistedValue from './utils/get-persisted-value'
|
|
@@ -40,8 +40,6 @@ export default function createPersistedState(storageKey: string, storage: Storag
|
|
|
40
40
|
applyValue(readPersisted(key, initialValue))
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const pendingOwnWrites = useRef<string[]>([])
|
|
44
|
-
|
|
45
43
|
const setPersistedState = useCallback(
|
|
46
44
|
(newState: React.SetStateAction<T>): void => {
|
|
47
45
|
const newValue = getNewValue<T>(newState, latestValue.current)
|
|
@@ -58,14 +56,12 @@ export default function createPersistedState(storageKey: string, storage: Storag
|
|
|
58
56
|
return
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
recordOwnWrite(pendingOwnWrites, newItem)
|
|
62
|
-
|
|
63
59
|
storage.set({ [safeStorageKey]: newItem })
|
|
64
60
|
},
|
|
65
61
|
[key, applyValue],
|
|
66
62
|
)
|
|
67
63
|
|
|
68
|
-
useStorageHandler<T>(key, safeStorageKey, applyValue, storage, initialValue
|
|
64
|
+
useStorageHandler<T>(key, safeStorageKey, applyValue, storage, initialValue)
|
|
69
65
|
|
|
70
66
|
return [state, setPersistedState]
|
|
71
67
|
}
|
|
@@ -42,50 +42,21 @@ function applyRemoval<T>(
|
|
|
42
42
|
applyValue(initialValue)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
// A list, not one slot: a write may still be awaiting its echo when the next one starts.
|
|
46
|
-
// Capped, because a backend that never reports back leaves every record unmatched.
|
|
47
|
-
const MAX_PENDING_OWN_WRITES = 8
|
|
48
|
-
|
|
49
|
-
/** Records an entry before it is written, because a backend may report the change before the write settles. */
|
|
50
|
-
export function recordOwnWrite(pendingOwnWrites: React.RefObject<string[]>, item: string): void {
|
|
51
|
-
const pending = pendingOwnWrites.current
|
|
52
|
-
|
|
53
|
-
if (pending.length >= MAX_PENDING_OWN_WRITES) pending.shift()
|
|
54
|
-
|
|
55
|
-
pending.push(item)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Applying a hook's own echo would re-decode the entry and re-render for a value it already holds.
|
|
59
|
-
function consumeOwnWriteEcho(entry: string, pendingOwnWrites: React.RefObject<string[]>): boolean {
|
|
60
|
-
const matched = pendingOwnWrites.current.indexOf(entry)
|
|
61
|
-
|
|
62
|
-
if (matched === -1) return false
|
|
63
|
-
|
|
64
|
-
// A backend reports writes in the order it took them, so a record still unmatched has no echo left.
|
|
65
|
-
pendingOwnWrites.current.splice(0, matched + 1)
|
|
66
|
-
|
|
67
|
-
return true
|
|
68
|
-
}
|
|
69
|
-
|
|
70
45
|
function createStorageHandler<T>(
|
|
71
46
|
itemKey: string,
|
|
72
47
|
storageKey: string,
|
|
73
48
|
applyValue: (value: T) => void,
|
|
74
49
|
latestInitialValue: React.RefObject<T | (() => T)>,
|
|
75
|
-
pendingOwnWrites: React.RefObject<string[]>,
|
|
76
50
|
) {
|
|
77
51
|
return (changes: { [key: string]: StorageChange }): void => {
|
|
78
52
|
for (const [key, change] of Object.entries(changes)) {
|
|
79
53
|
if (key !== storageKey) continue
|
|
80
54
|
|
|
81
|
-
// Ahead of the echo check, which needs an entry to match and a removal has none.
|
|
82
55
|
if (change.newValue === null || change.newValue === undefined) {
|
|
83
56
|
applyRemoval<T>(change, itemKey, applyValue, latestInitialValue)
|
|
84
57
|
continue
|
|
85
58
|
}
|
|
86
59
|
|
|
87
|
-
if (consumeOwnWriteEcho(change.newValue, pendingOwnWrites)) continue
|
|
88
|
-
|
|
89
60
|
const newValue = readStoredValue<T>(itemKey, change.newValue)
|
|
90
61
|
|
|
91
62
|
if (newValue.status === 'stored') applyValue(newValue.value)
|
|
@@ -99,7 +70,6 @@ export default function useStorageHandler<T>(
|
|
|
99
70
|
applyValue: (value: T) => void,
|
|
100
71
|
storage: AsyncStorage | Storage,
|
|
101
72
|
initialValue: T | (() => T),
|
|
102
|
-
pendingOwnWrites: React.RefObject<string[]>,
|
|
103
73
|
): void {
|
|
104
74
|
// A ref, not a dependency: an inline initial value changes identity every render and would churn it.
|
|
105
75
|
const latestInitialValue = useRef(initialValue)
|
|
@@ -107,7 +77,7 @@ export default function useStorageHandler<T>(
|
|
|
107
77
|
latestInitialValue.current = initialValue
|
|
108
78
|
|
|
109
79
|
useEffect(() => {
|
|
110
|
-
const handleStorage = createStorageHandler<T>(key, storageKey, applyValue, latestInitialValue
|
|
80
|
+
const handleStorage = createStorageHandler<T>(key, storageKey, applyValue, latestInitialValue)
|
|
111
81
|
|
|
112
82
|
storage.onChanged.addListener(handleStorage)
|
|
113
83
|
|
|
@@ -116,5 +86,5 @@ export default function useStorageHandler<T>(
|
|
|
116
86
|
storage.onChanged.removeListener(handleStorage)
|
|
117
87
|
}
|
|
118
88
|
}
|
|
119
|
-
}, [key, storage.onChanged, storageKey, applyValue
|
|
89
|
+
}, [key, storage.onChanged, storageKey, applyValue])
|
|
120
90
|
}
|