reactish-state 1.2.1-alpha.2 → 2.0.0-alpha.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/README.md +78 -56
- package/dist/cjs/index.cjs +2 -2
- package/dist/cjs/middleware/applyMiddleware.cjs +10 -0
- package/dist/cjs/middleware/immer.cjs +9 -0
- package/dist/cjs/middleware/persist.cjs +41 -0
- package/dist/{middleware/cjs → cjs/middleware}/reduxDevtools.cjs +10 -8
- package/dist/cjs/plugin/applyPlugin.cjs +5 -0
- package/dist/{plugin/cjs → cjs/plugin}/reduxDevtools.cjs +5 -4
- package/dist/cjs/vanilla/selector.cjs +8 -8
- package/dist/cjs/vanilla/state.cjs +6 -6
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/middleware/applyMiddleware.mjs +8 -0
- package/dist/esm/middleware/immer.mjs +7 -0
- package/dist/esm/middleware/persist.mjs +39 -0
- package/dist/{middleware/esm → esm/middleware}/reduxDevtools.mjs +10 -8
- package/dist/esm/plugin/applyPlugin.mjs +3 -0
- package/dist/{plugin/esm → esm/plugin}/reduxDevtools.mjs +5 -4
- package/dist/esm/vanilla/selector.mjs +8 -8
- package/dist/esm/vanilla/state.mjs +6 -6
- package/package.json +9 -9
- package/types/middleware/applyMiddleware.d.ts +2 -2
- package/types/middleware/persist.d.ts +8 -8
- package/types/middleware/reduxDevtools.d.ts +3 -5
- package/types/plugin/applyPlugin.d.ts +1 -1
- package/types/plugin/reduxDevtools.d.ts +3 -5
- package/types/react/useSnapshot.d.ts +2 -2
- package/types/types.d.ts +28 -18
- package/types/vanilla/selector.d.ts +4 -6
- package/types/vanilla/state.d.ts +4 -6
- package/dist/middleware/cjs/applyMiddleware.cjs +0 -10
- package/dist/middleware/cjs/immer.cjs +0 -9
- package/dist/middleware/cjs/persist.cjs +0 -39
- package/dist/middleware/esm/applyMiddleware.mjs +0 -8
- package/dist/middleware/esm/immer.mjs +0 -7
- package/dist/middleware/esm/persist.mjs +0 -37
- package/dist/plugin/cjs/applyPlugin.cjs +0 -5
- package/dist/plugin/esm/applyPlugin.mjs +0 -3
- /package/dist/{middleware/cjs → cjs/middleware}/index.cjs +0 -0
- /package/dist/{plugin/cjs → cjs/plugin}/index.cjs +0 -0
- /package/dist/{shim/cjs → cjs/shim}/index.cjs +0 -0
- /package/dist/{shim/cjs → cjs/shim}/reactShim.cjs +0 -0
- /package/dist/{middleware/esm → esm/middleware}/index.mjs +0 -0
- /package/dist/{plugin/esm → esm/plugin}/index.mjs +0 -0
- /package/dist/{shim/esm → esm/shim}/index.mjs +0 -0
- /package/dist/{shim/esm → esm/shim}/reactShim.mjs +0 -0
package/README.md
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
> Simple, decentralized (atomic) state management for React.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/reactish-state) [](https://www.npmjs.com/package/reactish-state) [](https://bundlejs.com/?q=reactish-state&treeshake=%5B*%5D&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%5D%7D%7D) [](https://bundlephobia.com/package/reactish-state)
|
|
6
6
|
|
|
7
7
|
💡 [Quick examples](#examples) 🔧 [TypeScript usage](#typescript-usage)
|
|
8
8
|
|
|
9
|
-
## ✨Highlights✨
|
|
9
|
+
## ✨ Highlights ✨
|
|
10
10
|
|
|
11
|
-
- Decentralized state management
|
|
12
|
-
-
|
|
13
|
-
- No
|
|
11
|
+
- Decentralized (atomic) state management
|
|
12
|
+
- Simple, unopinionated API
|
|
13
|
+
- No Context wrapper or prop drilling required
|
|
14
14
|
- React components re-render only on changes
|
|
15
15
|
- Compatible with React 18/19 concurrent rendering
|
|
16
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- Built-in memoized selectors
|
|
17
|
+
- Extensible with middleware and plugins
|
|
18
18
|
- State persistable to browser storage
|
|
19
|
-
-
|
|
20
|
-
-
|
|
19
|
+
- Redux DevTools support via middleware
|
|
20
|
+
- Fully compatible with React Compiler
|
|
21
|
+
- Ultra-lightweight: [<1KB](https://bundlejs.com/?q=reactish-state&treeshake=%5B*%5D&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%5D%7D%7D)
|
|
21
22
|
|
|
22
23
|
## Install
|
|
23
24
|
|
|
@@ -25,7 +26,38 @@
|
|
|
25
26
|
npm install reactish-state
|
|
26
27
|
```
|
|
27
28
|
|
|
28
|
-
##
|
|
29
|
+
## Table of Contents
|
|
30
|
+
|
|
31
|
+
- [Quick start](#quick-start)
|
|
32
|
+
- [State](#we-begin-by-creating-some-state)
|
|
33
|
+
- [State with actions](#a-state-can-also-have-custom-actions-bound-to-it)
|
|
34
|
+
- [Selectors](#selector-can-create-derived-state)
|
|
35
|
+
- [Usage in React](#use-the-state-and-selectors-in-your-react-components)
|
|
36
|
+
- [Why another library?](#why-another-state-management-library)
|
|
37
|
+
- [Why decentralized?](#why-decentralized-state-management)
|
|
38
|
+
- [Why not Zustand?](#why-choose-this-over-zustand)
|
|
39
|
+
- [Recipes](#recipes)
|
|
40
|
+
- [Immutable updates](#state-should-be-updated-immutably)
|
|
41
|
+
- [Memoized selectors](#selectors-are-memoized)
|
|
42
|
+
- [Async updates](#async-state-updates)
|
|
43
|
+
- [Accessing other state in actions](#accessing-other-state-or-selectors-inside-actions)
|
|
44
|
+
- [Usage outside React](#interacting-with-state-or-selectors-outside-react)
|
|
45
|
+
- [Destructuring actions](#destructuring-actions-for-easier-access)
|
|
46
|
+
- [useSelector](#selector-that-depends-on-props-or-local-state)
|
|
47
|
+
- [Redux-like reducers](#still-perfer-redux-like-reducers)
|
|
48
|
+
- [Middleware](#middleware)
|
|
49
|
+
- [Persist middleware](#persist-middleware)
|
|
50
|
+
- [Immer middleware](#immer-middleware)
|
|
51
|
+
- [Redux devtools middleware](#redux-devtools-middleware)
|
|
52
|
+
- [Multiple middleware](#using-multiple-middleware)
|
|
53
|
+
- [Different middleware](#using-different-middleware-in-different-states)
|
|
54
|
+
- [Plugins](#plugins)
|
|
55
|
+
- [Redux devtools plugin](#redux-devtools-plugin)
|
|
56
|
+
- [TypeScript usage](#typescript-usage)
|
|
57
|
+
- [Examples](#examples)
|
|
58
|
+
- [React 16/17 setup](#react-1617-setup)
|
|
59
|
+
|
|
60
|
+
# Quick start
|
|
29
61
|
|
|
30
62
|
### We begin by creating some state
|
|
31
63
|
|
|
@@ -384,21 +416,17 @@ dispatch({ type: "DECREASE", by: 7 });
|
|
|
384
416
|
console.log(countState.get()); // Print 3
|
|
385
417
|
```
|
|
386
418
|
|
|
387
|
-
|
|
419
|
+
# Middleware
|
|
388
420
|
|
|
389
|
-
You can enhance
|
|
421
|
+
You can enhance state functionality using middleware. Instead of the `state` export, use the `stateBuilder` export from the library. A middleware is a function that receives a state object and returns a new `set` function, which can add custom behavior while still calling the current `set` in the middleware chain.
|
|
390
422
|
|
|
391
423
|
```js
|
|
392
|
-
import {
|
|
393
|
-
|
|
394
|
-
const state =
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
set(...args);
|
|
399
|
-
// Log the state every time after calling `set`
|
|
400
|
-
console.log("New state", get());
|
|
401
|
-
}
|
|
424
|
+
import { stateBuilder } from "reactish-state";
|
|
425
|
+
|
|
426
|
+
const state = stateBuilder(({ set, get }) => (...args) => {
|
|
427
|
+
set(...args);
|
|
428
|
+
// Log the state every time after calling `set`
|
|
429
|
+
console.log("New state", get());
|
|
402
430
|
});
|
|
403
431
|
|
|
404
432
|
// Now the `state` function has middleware wired up
|
|
@@ -420,13 +448,13 @@ filterState.set("COMPLETED"); // Print "New state 'COMPLETED'"
|
|
|
420
448
|
You can save the state to browser storage using the `persist` middleware.
|
|
421
449
|
|
|
422
450
|
```js
|
|
423
|
-
import {
|
|
451
|
+
import { stateBuilder } from "reactish-state";
|
|
424
452
|
import { persist } from "reactish-state/middleware";
|
|
425
453
|
|
|
426
454
|
// Create the persist middleware,
|
|
427
455
|
// optionally provide a `prefix` to prepend to the keys in storage
|
|
428
456
|
const persistMiddleware = persist({ prefix: "myApp-" });
|
|
429
|
-
const state =
|
|
457
|
+
const state = stateBuilder(persistMiddleware.middleware);
|
|
430
458
|
|
|
431
459
|
const countState = state(
|
|
432
460
|
0,
|
|
@@ -457,10 +485,10 @@ const persistMiddleware = persist({ getStorage: () => sessionStorage });
|
|
|
457
485
|
You can update state mutably using the `immer` middleware.
|
|
458
486
|
|
|
459
487
|
```js
|
|
460
|
-
import {
|
|
488
|
+
import { stateBuilder } from "reactish-state";
|
|
461
489
|
import { immer } from "reactish-state/middleware/immer";
|
|
462
490
|
|
|
463
|
-
const state =
|
|
491
|
+
const state = stateBuilder(immer);
|
|
464
492
|
|
|
465
493
|
let todoId = 1;
|
|
466
494
|
const todos = state([], (set) => ({
|
|
@@ -488,10 +516,10 @@ todos.toggle(1);
|
|
|
488
516
|
This middleware provides integration with the Redux DevTools browser extension. Individual states are combined into a single object in Redux DevTools for easy inspection.
|
|
489
517
|
|
|
490
518
|
```js
|
|
491
|
-
import {
|
|
519
|
+
import { stateBuilder } from "reactish-state";
|
|
492
520
|
import { reduxDevtools } from "reactish-state/middleware";
|
|
493
521
|
|
|
494
|
-
const state =
|
|
522
|
+
const state = stateBuilder(reduxDevtools({ name: "todoApp" }));
|
|
495
523
|
|
|
496
524
|
const todos = state(
|
|
497
525
|
[],
|
|
@@ -523,14 +551,14 @@ const filter = state("ALL", null, { key: "filter" });
|
|
|
523
551
|
|
|
524
552
|
## Using multiple middleware
|
|
525
553
|
|
|
526
|
-
Middleware is chainable. You can use the `applyMiddleware` utility to chain multiple middleware and pass the result to `
|
|
554
|
+
Middleware is chainable. You can use the `applyMiddleware` utility to chain multiple middleware and pass the result to `stateBuilder`.
|
|
527
555
|
|
|
528
556
|
```js
|
|
529
557
|
import { applyMiddleware } from "reactish-state/middleware";
|
|
530
558
|
|
|
531
|
-
const state =
|
|
532
|
-
|
|
533
|
-
|
|
559
|
+
const state = stateBuilder(
|
|
560
|
+
applyMiddleware([reduxDevtools(), persist().middleware, immer])
|
|
561
|
+
);
|
|
534
562
|
```
|
|
535
563
|
|
|
536
564
|
## Using different middleware in different states
|
|
@@ -538,44 +566,38 @@ const state = createState({
|
|
|
538
566
|
This is naturally achievable thanks to the decentralized state model.
|
|
539
567
|
|
|
540
568
|
```js
|
|
541
|
-
const
|
|
542
|
-
const immerState =
|
|
569
|
+
const persistableState = stateBuilder(persist().middleware);
|
|
570
|
+
const immerState = stateBuilder(immer);
|
|
543
571
|
|
|
544
|
-
const visibilityFilter =
|
|
572
|
+
const visibilityFilter = persistableState("ALL"); // Will be persisted
|
|
545
573
|
const todos = immerState([]); // Can be mutated
|
|
546
574
|
```
|
|
547
575
|
|
|
548
576
|
This also eliminates the need to implement a whitelist or blacklist in the persist middleware.
|
|
549
577
|
|
|
550
|
-
|
|
578
|
+
# Plugins
|
|
551
579
|
|
|
552
|
-
While middleware enhances state, plugins allow you to hook into selectors. The key difference is that plugins don’t return a `set` function, as selectors are read-only. Similarly, you use the `
|
|
580
|
+
While middleware enhances state, plugins allow you to hook into selectors. The key difference is that plugins don’t return a `set` function, as selectors are read-only. Similarly, you use the `selectorBuilder` export from the library instead of `selector`.
|
|
553
581
|
|
|
554
582
|
```js
|
|
555
|
-
import { state,
|
|
556
|
-
|
|
557
|
-
const selector =
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
});
|
|
564
|
-
}
|
|
583
|
+
import { state, selectorBuilder } from "reactish-state";
|
|
584
|
+
|
|
585
|
+
const selector = selectorBuilder(({ get, subscribe, meta }) => {
|
|
586
|
+
subscribe(() => {
|
|
587
|
+
// Log the selector value every time it changes
|
|
588
|
+
// `meta` returns metadata of the selector
|
|
589
|
+
console.log(`${meta()} selector:`, get());
|
|
590
|
+
});
|
|
565
591
|
});
|
|
566
592
|
|
|
567
593
|
const countState = state(0);
|
|
568
594
|
const doubleSelector = selector(
|
|
569
595
|
countState,
|
|
570
596
|
(count) => count * 2,
|
|
571
|
-
// Provide
|
|
572
|
-
|
|
573
|
-
key: "double"
|
|
574
|
-
}
|
|
597
|
+
// Provide metadata in the last parameter to identify the selector
|
|
598
|
+
"double"
|
|
575
599
|
);
|
|
576
|
-
const squareSelector = selector(countState, (count) => count * count,
|
|
577
|
-
key: "square"
|
|
578
|
-
});
|
|
600
|
+
const squareSelector = selector(countState, (count) => count * count, "square");
|
|
579
601
|
|
|
580
602
|
countState.set(5); // Logs - double selector: 10, square selector: 25
|
|
581
603
|
```
|
|
@@ -587,10 +609,10 @@ Likewise, there is an `applyPlugin` function for applying multiple plugins.
|
|
|
587
609
|
Individual selectors are combined into a single object in Redux DevTools for easy inspection.
|
|
588
610
|
|
|
589
611
|
```js
|
|
590
|
-
import {
|
|
612
|
+
import { selectorBuilder } from "reactish-state";
|
|
591
613
|
import { reduxDevtools } from "reactish-state/plugin";
|
|
592
614
|
|
|
593
|
-
const selector =
|
|
615
|
+
const selector = selectorBuilder(reduxDevtools());
|
|
594
616
|
// Then use the `selector` as usual...
|
|
595
617
|
```
|
|
596
618
|
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -8,10 +8,10 @@ var shim = require('./react/shim.cjs');
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
exports.createState = state.createState;
|
|
12
11
|
exports.state = state.state;
|
|
13
|
-
exports.
|
|
12
|
+
exports.stateBuilder = state.stateBuilder;
|
|
14
13
|
exports.selector = selector.selector;
|
|
14
|
+
exports.selectorBuilder = selector.selectorBuilder;
|
|
15
15
|
exports.useSnapshot = useSnapshot.useSnapshot;
|
|
16
16
|
exports.useSelector = useSelector.useSelector;
|
|
17
17
|
exports.setReactShim = shim.setReactShim;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const applyMiddleware = (middlewares, {
|
|
4
|
+
fromRight
|
|
5
|
+
} = {}) => api => middlewares[fromRight ? 'reduceRight' : 'reduce']((set, middleware) => middleware ? middleware({
|
|
6
|
+
...api,
|
|
7
|
+
set
|
|
8
|
+
}) : set, api.set);
|
|
9
|
+
|
|
10
|
+
exports.applyMiddleware = applyMiddleware;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const persist = ({
|
|
4
|
+
prefix,
|
|
5
|
+
getStorage = () => localStorage
|
|
6
|
+
} = {}) => {
|
|
7
|
+
const states = [];
|
|
8
|
+
return {
|
|
9
|
+
middleware: ({
|
|
10
|
+
set,
|
|
11
|
+
get,
|
|
12
|
+
meta
|
|
13
|
+
}) => {
|
|
14
|
+
let key = meta()?.key;
|
|
15
|
+
if (process.env.NODE_ENV !== 'production' && !key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `persist` middleware is used.');
|
|
16
|
+
if (prefix) key = prefix + key;
|
|
17
|
+
states.push([key, set]);
|
|
18
|
+
return (...args) => {
|
|
19
|
+
set(...args);
|
|
20
|
+
try {
|
|
21
|
+
getStorage().setItem(key, JSON.stringify(get()));
|
|
22
|
+
} catch (_unused) {
|
|
23
|
+
/* continue regardless of error */
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
hydrate: () => {
|
|
28
|
+
states.forEach(([key, set]) => {
|
|
29
|
+
try {
|
|
30
|
+
const value = getStorage().getItem(key);
|
|
31
|
+
value != null && set(value !== 'undefined' ? JSON.parse(value) : undefined, `HYDRATE_${key}`);
|
|
32
|
+
} catch (_unused2) {
|
|
33
|
+
/* continue regardless of error */
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
states.length = 0;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
exports.persist = persist;
|
|
@@ -4,22 +4,24 @@ const reduxDevtools = ({
|
|
|
4
4
|
name
|
|
5
5
|
} = {}) => {
|
|
6
6
|
let devtoolsExt;
|
|
7
|
-
if (process.env.NODE_ENV === 'production' || typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__))
|
|
7
|
+
if (process.env.NODE_ENV === 'production' || typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
8
10
|
const devtools = devtoolsExt.connect({
|
|
9
11
|
name
|
|
10
12
|
});
|
|
11
13
|
const mergedState = {};
|
|
12
14
|
return ({
|
|
13
15
|
set,
|
|
14
|
-
get
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
get,
|
|
17
|
+
meta
|
|
18
|
+
}) => {
|
|
19
|
+
const key = meta()?.key;
|
|
20
|
+
if (process.env.NODE_ENV !== 'production' && !key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` middleware is used.');
|
|
18
21
|
mergedState[key] = get();
|
|
19
22
|
devtools.init(mergedState);
|
|
20
|
-
return (
|
|
21
|
-
|
|
22
|
-
set(...args);
|
|
23
|
+
return (value, action) => {
|
|
24
|
+
set(value, action);
|
|
23
25
|
mergedState[key] = get();
|
|
24
26
|
devtools.send(typeof action === 'string' ? {
|
|
25
27
|
type: action
|
|
@@ -11,10 +11,11 @@ const reduxDevtools = ({
|
|
|
11
11
|
const mergedState = {};
|
|
12
12
|
return ({
|
|
13
13
|
get,
|
|
14
|
-
subscribe
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
subscribe,
|
|
15
|
+
meta
|
|
16
|
+
}) => {
|
|
17
|
+
const key = meta()?.key;
|
|
18
|
+
if (process.env.NODE_ENV !== 'production' && !key) throw new Error('[reactish-state] selector should be provided with a string `key` in the config object when the `reduxDevtools` plugin is used.');
|
|
18
19
|
const updateState = () => {
|
|
19
20
|
mergedState[key] = get();
|
|
20
21
|
devtools.init(mergedState);
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
var utils = require('../utils.cjs');
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
plugin
|
|
7
|
-
} = {}) => (...items) => {
|
|
5
|
+
const selectorBuilder = plugin => (...items) => {
|
|
8
6
|
const length = items.length;
|
|
9
7
|
const cutoff = typeof items[length - 1] === 'function' ? length - 1 : length - 2;
|
|
10
8
|
const selectorFunc = items[cutoff];
|
|
11
|
-
const
|
|
9
|
+
const metadata = items[cutoff + 1];
|
|
12
10
|
items.length = cutoff;
|
|
13
11
|
let cache;
|
|
14
12
|
const selector = {
|
|
@@ -19,12 +17,14 @@ const createSelector = ({
|
|
|
19
17
|
cache = [args, value];
|
|
20
18
|
return value;
|
|
21
19
|
},
|
|
22
|
-
subscribe: utils.createSubscriber(items)
|
|
20
|
+
subscribe: utils.createSubscriber(items),
|
|
21
|
+
meta: () => metadata
|
|
23
22
|
};
|
|
24
|
-
plugin?.(selector
|
|
23
|
+
plugin?.(selector);
|
|
25
24
|
return selector;
|
|
25
|
+
// Wrap TSelectorMeta in a tuple to prevent conditional type distribution;
|
|
26
26
|
};
|
|
27
|
-
const selector = /*#__PURE__*/
|
|
27
|
+
const selector = /*#__PURE__*/selectorBuilder();
|
|
28
28
|
|
|
29
|
-
exports.createSelector = createSelector;
|
|
30
29
|
exports.selector = selector;
|
|
30
|
+
exports.selectorBuilder = selectorBuilder;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
middleware
|
|
5
|
-
} = {}) => (initialValue, actionBuilder, config) => {
|
|
3
|
+
const stateBuilder = middleware => (initialValue, actionBuilder, metadata) => {
|
|
6
4
|
let value = initialValue;
|
|
7
5
|
const listeners = new Set();
|
|
8
6
|
const get = () => value;
|
|
9
7
|
const readonlyState = {
|
|
10
8
|
get,
|
|
9
|
+
meta: () => metadata,
|
|
11
10
|
subscribe: listener => {
|
|
12
11
|
listeners.add(listener);
|
|
13
12
|
return () => listeners.delete(listener);
|
|
@@ -24,14 +23,15 @@ const createState = ({
|
|
|
24
23
|
if (middleware) set = middleware({
|
|
25
24
|
...readonlyState,
|
|
26
25
|
set
|
|
27
|
-
}
|
|
26
|
+
});
|
|
28
27
|
return {
|
|
29
28
|
...actionBuilder?.(set, get),
|
|
30
29
|
...readonlyState,
|
|
31
30
|
set
|
|
32
31
|
};
|
|
32
|
+
// Wrap TStateMeta in a tuple to prevent conditional type distribution
|
|
33
33
|
};
|
|
34
|
-
const state = /*#__PURE__*/
|
|
34
|
+
const state = /*#__PURE__*/stateBuilder();
|
|
35
35
|
|
|
36
|
-
exports.createState = createState;
|
|
37
36
|
exports.state = state;
|
|
37
|
+
exports.stateBuilder = stateBuilder;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
1
|
+
export { state, stateBuilder } from './vanilla/state.mjs';
|
|
2
|
+
export { selector, selectorBuilder } from './vanilla/selector.mjs';
|
|
3
3
|
export { useSnapshot } from './react/useSnapshot.mjs';
|
|
4
4
|
export { useSelector } from './react/useSelector.mjs';
|
|
5
5
|
export { setReactShim } from './react/shim.mjs';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const persist = ({
|
|
2
|
+
prefix,
|
|
3
|
+
getStorage = () => localStorage
|
|
4
|
+
} = {}) => {
|
|
5
|
+
const states = [];
|
|
6
|
+
return {
|
|
7
|
+
middleware: ({
|
|
8
|
+
set,
|
|
9
|
+
get,
|
|
10
|
+
meta
|
|
11
|
+
}) => {
|
|
12
|
+
let key = meta()?.key;
|
|
13
|
+
if (process.env.NODE_ENV !== 'production' && !key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `persist` middleware is used.');
|
|
14
|
+
if (prefix) key = prefix + key;
|
|
15
|
+
states.push([key, set]);
|
|
16
|
+
return (...args) => {
|
|
17
|
+
set(...args);
|
|
18
|
+
try {
|
|
19
|
+
getStorage().setItem(key, JSON.stringify(get()));
|
|
20
|
+
} catch (_unused) {
|
|
21
|
+
/* continue regardless of error */
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
hydrate: () => {
|
|
26
|
+
states.forEach(([key, set]) => {
|
|
27
|
+
try {
|
|
28
|
+
const value = getStorage().getItem(key);
|
|
29
|
+
value != null && set(value !== 'undefined' ? JSON.parse(value) : undefined, `HYDRATE_${key}`);
|
|
30
|
+
} catch (_unused2) {
|
|
31
|
+
/* continue regardless of error */
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
states.length = 0;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { persist };
|
|
@@ -2,22 +2,24 @@ const reduxDevtools = ({
|
|
|
2
2
|
name
|
|
3
3
|
} = {}) => {
|
|
4
4
|
let devtoolsExt;
|
|
5
|
-
if (process.env.NODE_ENV === 'production' || typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__))
|
|
5
|
+
if (process.env.NODE_ENV === 'production' || typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
6
8
|
const devtools = devtoolsExt.connect({
|
|
7
9
|
name
|
|
8
10
|
});
|
|
9
11
|
const mergedState = {};
|
|
10
12
|
return ({
|
|
11
13
|
set,
|
|
12
|
-
get
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
get,
|
|
15
|
+
meta
|
|
16
|
+
}) => {
|
|
17
|
+
const key = meta()?.key;
|
|
18
|
+
if (process.env.NODE_ENV !== 'production' && !key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` middleware is used.');
|
|
16
19
|
mergedState[key] = get();
|
|
17
20
|
devtools.init(mergedState);
|
|
18
|
-
return (
|
|
19
|
-
|
|
20
|
-
set(...args);
|
|
21
|
+
return (value, action) => {
|
|
22
|
+
set(value, action);
|
|
21
23
|
mergedState[key] = get();
|
|
22
24
|
devtools.send(typeof action === 'string' ? {
|
|
23
25
|
type: action
|
|
@@ -9,10 +9,11 @@ const reduxDevtools = ({
|
|
|
9
9
|
const mergedState = {};
|
|
10
10
|
return ({
|
|
11
11
|
get,
|
|
12
|
-
subscribe
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
subscribe,
|
|
13
|
+
meta
|
|
14
|
+
}) => {
|
|
15
|
+
const key = meta()?.key;
|
|
16
|
+
if (process.env.NODE_ENV !== 'production' && !key) throw new Error('[reactish-state] selector should be provided with a string `key` in the config object when the `reduxDevtools` plugin is used.');
|
|
16
17
|
const updateState = () => {
|
|
17
18
|
mergedState[key] = get();
|
|
18
19
|
devtools.init(mergedState);
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { createSubscriber, getSelectorValues, isEqual } from '../utils.mjs';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
plugin
|
|
5
|
-
} = {}) => (...items) => {
|
|
3
|
+
const selectorBuilder = plugin => (...items) => {
|
|
6
4
|
const length = items.length;
|
|
7
5
|
const cutoff = typeof items[length - 1] === 'function' ? length - 1 : length - 2;
|
|
8
6
|
const selectorFunc = items[cutoff];
|
|
9
|
-
const
|
|
7
|
+
const metadata = items[cutoff + 1];
|
|
10
8
|
items.length = cutoff;
|
|
11
9
|
let cache;
|
|
12
10
|
const selector = {
|
|
@@ -17,11 +15,13 @@ const createSelector = ({
|
|
|
17
15
|
cache = [args, value];
|
|
18
16
|
return value;
|
|
19
17
|
},
|
|
20
|
-
subscribe: createSubscriber(items)
|
|
18
|
+
subscribe: createSubscriber(items),
|
|
19
|
+
meta: () => metadata
|
|
21
20
|
};
|
|
22
|
-
plugin?.(selector
|
|
21
|
+
plugin?.(selector);
|
|
23
22
|
return selector;
|
|
23
|
+
// Wrap TSelectorMeta in a tuple to prevent conditional type distribution;
|
|
24
24
|
};
|
|
25
|
-
const selector = /*#__PURE__*/
|
|
25
|
+
const selector = /*#__PURE__*/selectorBuilder();
|
|
26
26
|
|
|
27
|
-
export {
|
|
27
|
+
export { selector, selectorBuilder };
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
const
|
|
2
|
-
middleware
|
|
3
|
-
} = {}) => (initialValue, actionBuilder, config) => {
|
|
1
|
+
const stateBuilder = middleware => (initialValue, actionBuilder, metadata) => {
|
|
4
2
|
let value = initialValue;
|
|
5
3
|
const listeners = new Set();
|
|
6
4
|
const get = () => value;
|
|
7
5
|
const readonlyState = {
|
|
8
6
|
get,
|
|
7
|
+
meta: () => metadata,
|
|
9
8
|
subscribe: listener => {
|
|
10
9
|
listeners.add(listener);
|
|
11
10
|
return () => listeners.delete(listener);
|
|
@@ -22,13 +21,14 @@ const createState = ({
|
|
|
22
21
|
if (middleware) set = middleware({
|
|
23
22
|
...readonlyState,
|
|
24
23
|
set
|
|
25
|
-
}
|
|
24
|
+
});
|
|
26
25
|
return {
|
|
27
26
|
...actionBuilder?.(set, get),
|
|
28
27
|
...readonlyState,
|
|
29
28
|
set
|
|
30
29
|
};
|
|
30
|
+
// Wrap TStateMeta in a tuple to prevent conditional type distribution
|
|
31
31
|
};
|
|
32
|
-
const state = /*#__PURE__*/
|
|
32
|
+
const state = /*#__PURE__*/stateBuilder();
|
|
33
33
|
|
|
34
|
-
export {
|
|
34
|
+
export { state, stateBuilder };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reactish-state",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-alpha.0",
|
|
4
4
|
"description": "Simple, decentralized (atomic) state management for React.",
|
|
5
5
|
"author": "Zheng Song",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,23 +50,23 @@
|
|
|
50
50
|
},
|
|
51
51
|
"./middleware": {
|
|
52
52
|
"types": "./types/middleware/index.d.ts",
|
|
53
|
-
"require": "./dist/middleware/
|
|
54
|
-
"default": "./dist/middleware/
|
|
53
|
+
"require": "./dist/cjs/middleware/index.cjs",
|
|
54
|
+
"default": "./dist/esm/middleware/index.mjs"
|
|
55
55
|
},
|
|
56
56
|
"./middleware/immer": {
|
|
57
57
|
"types": "./types/middleware/immer.d.ts",
|
|
58
|
-
"require": "./dist/middleware/
|
|
59
|
-
"default": "./dist/middleware/
|
|
58
|
+
"require": "./dist/cjs/middleware/immer.cjs",
|
|
59
|
+
"default": "./dist/esm/middleware/immer.mjs"
|
|
60
60
|
},
|
|
61
61
|
"./plugin": {
|
|
62
62
|
"types": "./types/plugin/index.d.ts",
|
|
63
|
-
"require": "./dist/plugin/
|
|
64
|
-
"default": "./dist/plugin/
|
|
63
|
+
"require": "./dist/cjs/plugin/index.cjs",
|
|
64
|
+
"default": "./dist/esm/plugin/index.mjs"
|
|
65
65
|
},
|
|
66
66
|
"./shim": {
|
|
67
67
|
"types": "./types/shim/index.d.ts",
|
|
68
|
-
"require": "./dist/shim/
|
|
69
|
-
"default": "./dist/shim/
|
|
68
|
+
"require": "./dist/cjs/shim/index.cjs",
|
|
69
|
+
"default": "./dist/esm/shim/index.mjs"
|
|
70
70
|
},
|
|
71
71
|
"./package.json": "./package.json"
|
|
72
72
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Middleware } from '../types';
|
|
2
|
-
declare const applyMiddleware: <
|
|
2
|
+
declare const applyMiddleware: <TStateMeta>(middlewares: (Middleware<TStateMeta> | undefined)[], options?: {
|
|
3
3
|
fromRight?: boolean;
|
|
4
|
-
}) => Middleware<
|
|
4
|
+
}) => Middleware<TStateMeta>;
|
|
5
5
|
export { applyMiddleware };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { Middleware,
|
|
2
|
-
interface
|
|
3
|
-
|
|
1
|
+
import type { Middleware, Metadata } from '../types';
|
|
2
|
+
interface Persist<TStateMeta extends Metadata> {
|
|
3
|
+
middleware: Middleware<TStateMeta>;
|
|
4
|
+
hydrate: () => void;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
+
declare const persist: <TStateMeta extends Metadata>({ prefix, getStorage }?: {
|
|
6
7
|
prefix?: string;
|
|
7
|
-
getStorage?: () => Pick<Storage,
|
|
8
|
-
}) =>
|
|
9
|
-
|
|
10
|
-
export type { Persist, PersistMiddleware };
|
|
8
|
+
getStorage?: () => Pick<Storage, "getItem" | "setItem">;
|
|
9
|
+
}) => Persist<TStateMeta>;
|
|
10
|
+
export type { Persist };
|
|
11
11
|
export { persist };
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { Middleware,
|
|
2
|
-
|
|
1
|
+
import type { Middleware, Metadata } from '../types';
|
|
2
|
+
declare const reduxDevtools: <TStateMeta extends Metadata>({ name }?: {
|
|
3
3
|
name?: string;
|
|
4
|
-
}) => Middleware<
|
|
5
|
-
declare const reduxDevtools: ReduxDevtools;
|
|
6
|
-
export type { ReduxDevtools };
|
|
4
|
+
}) => Middleware<TStateMeta> | undefined;
|
|
7
5
|
export { reduxDevtools };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Plugin } from '../types';
|
|
2
|
-
declare const applyPlugin: <
|
|
2
|
+
declare const applyPlugin: <TSelectorMeta>(plugins: (Plugin<TSelectorMeta> | undefined)[]) => Plugin<TSelectorMeta>;
|
|
3
3
|
export { applyPlugin };
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { Plugin,
|
|
2
|
-
|
|
1
|
+
import type { Plugin, Metadata } from '../types';
|
|
2
|
+
declare const reduxDevtools: <TSelectorMeta extends Metadata>({ name }?: {
|
|
3
3
|
name?: string;
|
|
4
|
-
}) => Plugin<
|
|
5
|
-
declare const reduxDevtools: ReduxDevtools;
|
|
6
|
-
export type { ReduxDevtools };
|
|
4
|
+
}) => Plugin<TSelectorMeta> | undefined;
|
|
7
5
|
export { reduxDevtools };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
declare const useSnapshot: <TValue>({ subscribe, get }:
|
|
1
|
+
import type { Observable } from '../types';
|
|
2
|
+
declare const useSnapshot: <TValue>({ subscribe, get }: Observable<TValue>) => TValue;
|
|
3
3
|
export { useSnapshot };
|
package/types/types.d.ts
CHANGED
|
@@ -1,35 +1,42 @@
|
|
|
1
|
+
export interface Metadata {
|
|
2
|
+
key: string;
|
|
3
|
+
}
|
|
1
4
|
export type Getter<TValue> = () => TValue;
|
|
2
5
|
export type Setter<TValue, TContext = unknown> = (newValue: TValue | ((value: TValue) => TValue), context?: TContext) => void;
|
|
3
6
|
export type Unsubscriber = () => void;
|
|
4
7
|
export type StateListener<TValue> = (nextValue: TValue, prevValue: TValue) => void;
|
|
5
8
|
export type StateSubscriber<TValue> = (listener: StateListener<TValue>) => Unsubscriber;
|
|
6
|
-
export interface State<TValue, TContext = unknown> {
|
|
9
|
+
export interface State<TValue, TMeta = unknown, TContext = unknown> {
|
|
7
10
|
get: Getter<TValue>;
|
|
8
11
|
set: Setter<TValue, TContext>;
|
|
9
12
|
subscribe: StateSubscriber<TValue>;
|
|
13
|
+
meta: () => TMeta;
|
|
14
|
+
}
|
|
15
|
+
export type StateWithAction<TValue, TAction, TMeta = unknown, TContext = unknown> = Omit<TAction, keyof State<TValue, TMeta, TContext>> & State<TValue, TMeta, TContext>;
|
|
16
|
+
export type ActionBuilder<TValue, TAction, TContext = unknown> = (set: Setter<TValue, TContext>, get: Getter<TValue>) => TAction;
|
|
17
|
+
export interface StateBuilder {
|
|
18
|
+
<TValue, TContext = unknown>(): State<TValue | undefined, undefined, TContext>;
|
|
19
|
+
<TValue, TContext = unknown>(initialValue: TValue): State<TValue, undefined, TContext>;
|
|
20
|
+
<TValue, TMeta, TContext = unknown>(initialValue: TValue, actionBuilder: null | undefined, metadata: TMeta): State<TValue, TMeta, TContext>;
|
|
21
|
+
<TValue, TAction, TContext = unknown>(initialValue: TValue, actionBuilder: ActionBuilder<TValue, TAction, TContext>): StateWithAction<TValue, TAction, undefined, TContext>;
|
|
22
|
+
<TValue, TAction, TMeta, TContext = unknown>(initialValue: TValue, actionBuilder: ActionBuilder<TValue, TAction, TContext>, metadata: TMeta): StateWithAction<TValue, TAction, TMeta, TContext>;
|
|
10
23
|
}
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<TValue, TContext = unknown>(): State<TValue | undefined, TContext>;
|
|
15
|
-
<TValue, TContext = unknown>(initialValue: TValue): State<TValue, TContext>;
|
|
16
|
-
<TValue, TContext = unknown>(initialValue: TValue, actionBuilder: null | undefined, config?: TConfig): State<TValue, TContext>;
|
|
17
|
-
<TValue, TAction, TContext = unknown>(initialValue: TValue, actionBuilder: ActionBuilder<TValue, TAction, TContext>, config?: TConfig): StateWithAction<TValue, TAction, TContext>;
|
|
24
|
+
export interface StateBuilderWithMeta<TStateMeta> {
|
|
25
|
+
<TValue, TMeta extends TStateMeta, TContext = unknown>(initialValue: TValue, actionBuilder: null | undefined, metadata: TMeta): State<TValue, TMeta, TContext>;
|
|
26
|
+
<TValue, TAction, TMeta extends TStateMeta, TContext = unknown>(initialValue: TValue, actionBuilder: ActionBuilder<TValue, TAction, TContext>, metadata: TMeta): StateWithAction<TValue, TAction, TMeta, TContext>;
|
|
18
27
|
}
|
|
19
28
|
export type SelectorListener = () => void;
|
|
20
29
|
export type SelectorSubscriber = (listener: SelectorListener) => Unsubscriber;
|
|
21
|
-
export interface
|
|
30
|
+
export interface Observable<TValue> {
|
|
22
31
|
get: Getter<TValue>;
|
|
23
32
|
subscribe: SelectorSubscriber;
|
|
24
33
|
}
|
|
25
|
-
export interface
|
|
26
|
-
|
|
34
|
+
export interface Selector<TValue, TMeta = unknown> extends Observable<TValue> {
|
|
35
|
+
meta: () => TMeta;
|
|
27
36
|
}
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export interface Plugin<TConfig = unknown> {
|
|
32
|
-
<TValue>(selector: Selector<TValue>, config?: TConfig): void;
|
|
37
|
+
export type Middleware<TStateMeta = never> = <TValue, TMeta extends TStateMeta, TContext = unknown>(state: State<TValue, TMeta, TContext>) => Setter<TValue, TContext>;
|
|
38
|
+
export interface Plugin<TSelectorMeta = never> {
|
|
39
|
+
<TValue, TMeta extends TSelectorMeta>(selector: Selector<TValue, TMeta>): void;
|
|
33
40
|
}
|
|
34
41
|
export type SelectorArray = Selector<unknown>[];
|
|
35
42
|
export type SelectorValueArray<TArray extends SelectorArray> = {
|
|
@@ -40,7 +47,10 @@ export type SelectorParams<TArray extends SelectorArray, TValue> = [
|
|
|
40
47
|
...TArray,
|
|
41
48
|
SelectorFunc<TArray, TValue>
|
|
42
49
|
];
|
|
43
|
-
export interface SelectorBuilder
|
|
50
|
+
export interface SelectorBuilder {
|
|
44
51
|
<TArray extends SelectorArray, TValue>(...items: SelectorParams<TArray, TValue>): Selector<TValue>;
|
|
45
|
-
<TArray extends SelectorArray, TValue>(...items: [...SelectorParams<TArray, TValue>,
|
|
52
|
+
<TArray extends SelectorArray, TValue, TMeta>(...items: [...SelectorParams<TArray, TValue>, TMeta]): Selector<TValue>;
|
|
53
|
+
}
|
|
54
|
+
export interface SelectorBuilderWithMeta<TSelectorMeta> {
|
|
55
|
+
<TArray extends SelectorArray, TValue, TMeta extends TSelectorMeta>(...items: [...SelectorParams<TArray, TValue>, TMeta]): Selector<TValue>;
|
|
46
56
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { Plugin, SelectorBuilder } from '../types';
|
|
2
|
-
declare const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
declare const selector: SelectorBuilder<unknown>;
|
|
6
|
-
export { selector, createSelector };
|
|
1
|
+
import type { Plugin, SelectorBuilder, SelectorBuilderWithMeta } from '../types';
|
|
2
|
+
declare const selectorBuilder: <TSelectorMeta = never>(plugin?: Plugin<TSelectorMeta>) => [TSelectorMeta] extends [never] ? SelectorBuilder : SelectorBuilderWithMeta<TSelectorMeta>;
|
|
3
|
+
declare const selector: SelectorBuilder;
|
|
4
|
+
export { selector, selectorBuilder };
|
package/types/vanilla/state.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { StateBuilder, Middleware } from '../types';
|
|
2
|
-
declare const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
declare const state: StateBuilder<unknown>;
|
|
6
|
-
export { state, createState };
|
|
1
|
+
import type { StateBuilder, StateBuilderWithMeta, Middleware } from '../types';
|
|
2
|
+
declare const stateBuilder: <TStateMeta = never>(middleware?: Middleware<TStateMeta>) => [TStateMeta] extends [never] ? StateBuilder : StateBuilderWithMeta<TStateMeta>;
|
|
3
|
+
declare const state: StateBuilder;
|
|
4
|
+
export { state, stateBuilder };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const applyMiddleware = (middlewares, {
|
|
4
|
-
fromRight
|
|
5
|
-
} = {}) => (api, config) => middlewares[fromRight ? 'reduceRight' : 'reduce']((set, middleware) => middleware ? middleware({
|
|
6
|
-
...api,
|
|
7
|
-
set
|
|
8
|
-
}, config) : set, api.set);
|
|
9
|
-
|
|
10
|
-
exports.applyMiddleware = applyMiddleware;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const persist = ({
|
|
4
|
-
prefix,
|
|
5
|
-
getStorage = () => localStorage
|
|
6
|
-
} = {}) => {
|
|
7
|
-
const states = [];
|
|
8
|
-
const middleware = ({
|
|
9
|
-
set,
|
|
10
|
-
get
|
|
11
|
-
}, config) => {
|
|
12
|
-
let key = config?.key || '';
|
|
13
|
-
if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `persist` middleware is used.');
|
|
14
|
-
if (prefix) key = prefix + key;
|
|
15
|
-
states.push([key, set]);
|
|
16
|
-
return (...args) => {
|
|
17
|
-
set(...args);
|
|
18
|
-
try {
|
|
19
|
-
getStorage().setItem(key, JSON.stringify(get()));
|
|
20
|
-
} catch (_unused) {
|
|
21
|
-
/* continue regardless of error */
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
middleware.hydrate = () => {
|
|
26
|
-
states.forEach(([key, set]) => {
|
|
27
|
-
try {
|
|
28
|
-
const value = getStorage().getItem(key);
|
|
29
|
-
value != null && set(value !== 'undefined' ? JSON.parse(value) : undefined, `HYDRATE_${key}`);
|
|
30
|
-
} catch (_unused2) {
|
|
31
|
-
/* continue regardless of error */
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
states.length = 0;
|
|
35
|
-
};
|
|
36
|
-
return middleware;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
exports.persist = persist;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
const persist = ({
|
|
2
|
-
prefix,
|
|
3
|
-
getStorage = () => localStorage
|
|
4
|
-
} = {}) => {
|
|
5
|
-
const states = [];
|
|
6
|
-
const middleware = ({
|
|
7
|
-
set,
|
|
8
|
-
get
|
|
9
|
-
}, config) => {
|
|
10
|
-
let key = config?.key || '';
|
|
11
|
-
if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `persist` middleware is used.');
|
|
12
|
-
if (prefix) key = prefix + key;
|
|
13
|
-
states.push([key, set]);
|
|
14
|
-
return (...args) => {
|
|
15
|
-
set(...args);
|
|
16
|
-
try {
|
|
17
|
-
getStorage().setItem(key, JSON.stringify(get()));
|
|
18
|
-
} catch (_unused) {
|
|
19
|
-
/* continue regardless of error */
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
middleware.hydrate = () => {
|
|
24
|
-
states.forEach(([key, set]) => {
|
|
25
|
-
try {
|
|
26
|
-
const value = getStorage().getItem(key);
|
|
27
|
-
value != null && set(value !== 'undefined' ? JSON.parse(value) : undefined, `HYDRATE_${key}`);
|
|
28
|
-
} catch (_unused2) {
|
|
29
|
-
/* continue regardless of error */
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
states.length = 0;
|
|
33
|
-
};
|
|
34
|
-
return middleware;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export { persist };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|