reactish-state 1.2.1-alpha.0 → 1.2.1-alpha.1
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 +4 -2
- package/dist/cjs/react/useSelector.cjs +11 -19
- package/dist/cjs/react/useSnapshot.cjs +2 -2
- package/dist/cjs/utils.cjs +1 -1
- package/dist/cjs/vanilla/selector.cjs +3 -6
- package/dist/cjs/vanilla/state.cjs +11 -10
- package/dist/esm/react/useSelector.mjs +11 -19
- package/dist/esm/react/useSnapshot.mjs +2 -2
- package/dist/esm/utils.mjs +1 -1
- package/dist/esm/vanilla/selector.mjs +3 -6
- package/dist/esm/vanilla/state.mjs +11 -10
- package/dist/plugin/cjs/reduxDevtools.cjs +1 -1
- package/dist/plugin/esm/reduxDevtools.mjs +1 -1
- package/package.json +1 -1
- package/types/react/useSnapshot.d.ts +1 -1
- package/types/types.d.ts +2 -2
package/README.md
CHANGED
|
@@ -273,8 +273,10 @@ const count = countState.get();
|
|
|
273
273
|
const triple = tripleSelector.get();
|
|
274
274
|
|
|
275
275
|
// Listen for updates
|
|
276
|
-
const unsub1 = countState.
|
|
277
|
-
const unsub2 = tripleSelector.
|
|
276
|
+
const unsub1 = countState.subscribe(() => console.log(countState.get()));
|
|
277
|
+
const unsub2 = tripleSelector.subscribe(() =>
|
|
278
|
+
console.log(tripleSelector.get())
|
|
279
|
+
);
|
|
278
280
|
|
|
279
281
|
// Updating `countState` will trigger both listeners
|
|
280
282
|
countState.set(10);
|
|
@@ -9,26 +9,18 @@ const useSelector = (selectorParamFactory, deps) => {
|
|
|
9
9
|
const cutoff = items.length - 1;
|
|
10
10
|
const selectorFunc = items[cutoff];
|
|
11
11
|
items.length = cutoff;
|
|
12
|
-
const [context] = React.useState(() => (
|
|
13
|
-
sub: utils.createSubscriber(items)
|
|
14
|
-
}));
|
|
15
|
-
const get = () => {
|
|
16
|
-
const {
|
|
17
|
-
cache
|
|
18
|
-
} = context;
|
|
19
|
-
const selectorValues = utils.getSelectorValues(items);
|
|
20
|
-
const args = selectorValues.concat(deps || selectorFunc);
|
|
21
|
-
if (cache && utils.isEqual(args, cache.args)) return cache.val;
|
|
22
|
-
const val = selectorFunc(...selectorValues);
|
|
23
|
-
context.cache = {
|
|
24
|
-
args,
|
|
25
|
-
val
|
|
26
|
-
};
|
|
27
|
-
return val;
|
|
28
|
-
};
|
|
12
|
+
const [context] = React.useState(() => [utils.createSubscriber(items)]);
|
|
29
13
|
return useSnapshot.useSnapshot({
|
|
30
|
-
get
|
|
31
|
-
|
|
14
|
+
get: () => {
|
|
15
|
+
const cache = context[1];
|
|
16
|
+
const selectorValues = utils.getSelectorValues(items);
|
|
17
|
+
const args = selectorValues.concat(deps || selectorFunc);
|
|
18
|
+
if (cache && utils.isEqual(args, cache[0])) return cache[1];
|
|
19
|
+
const val = selectorFunc(...selectorValues);
|
|
20
|
+
context[1] = [args, val];
|
|
21
|
+
return val;
|
|
22
|
+
},
|
|
23
|
+
subscribe: context[0]
|
|
32
24
|
});
|
|
33
25
|
};
|
|
34
26
|
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
var shim = require('./shim.cjs');
|
|
4
4
|
|
|
5
5
|
const useSnapshot = ({
|
|
6
|
-
|
|
6
|
+
subscribe,
|
|
7
7
|
get
|
|
8
8
|
}) => {
|
|
9
9
|
if (process.env.NODE_ENV !== 'production' && !shim.useSyncExternalStore) {
|
|
10
10
|
throw new Error('[reactish-state] Shim setup is required for React 16/17. See: https://github.com/szhsin/reactish-state/tree/master?tab=readme-ov-file#react-1617-setup');
|
|
11
11
|
}
|
|
12
|
-
return shim.useSyncExternalStore(
|
|
12
|
+
return shim.useSyncExternalStore(subscribe, get, get);
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
exports.useSnapshot = useSnapshot;
|
package/dist/cjs/utils.cjs
CHANGED
|
@@ -7,7 +7,7 @@ const isEqual = (args1, args2) => {
|
|
|
7
7
|
return true;
|
|
8
8
|
};
|
|
9
9
|
const createSubscriber = items => listener => {
|
|
10
|
-
const unsubscribers = items.map(item => item.
|
|
10
|
+
const unsubscribers = items.map(item => item.subscribe(listener));
|
|
11
11
|
return () => unsubscribers.forEach(unsubscribe => unsubscribe());
|
|
12
12
|
};
|
|
13
13
|
const getSelectorValues = items => items.map(item => item.get());
|
|
@@ -16,15 +16,12 @@ const createSelector = ({
|
|
|
16
16
|
const selector = {
|
|
17
17
|
get: () => {
|
|
18
18
|
const args = utils.getSelectorValues(items);
|
|
19
|
-
if (cache && utils.isEqual(args, cache
|
|
19
|
+
if (cache && utils.isEqual(args, cache[0])) return cache[1];
|
|
20
20
|
const val = selectorFunc(...args);
|
|
21
|
-
cache =
|
|
22
|
-
args,
|
|
23
|
-
val
|
|
24
|
-
};
|
|
21
|
+
cache = [args, val];
|
|
25
22
|
return val;
|
|
26
23
|
},
|
|
27
|
-
|
|
24
|
+
subscribe: utils.createSubscriber(items)
|
|
28
25
|
};
|
|
29
26
|
plugin?.(selector, config);
|
|
30
27
|
return selector;
|
|
@@ -6,6 +6,13 @@ const createState = ({
|
|
|
6
6
|
let value = initialValue;
|
|
7
7
|
const listeners = new Set();
|
|
8
8
|
const get = () => value;
|
|
9
|
+
const readonlyState = {
|
|
10
|
+
get,
|
|
11
|
+
subscribe: listener => {
|
|
12
|
+
listeners.add(listener);
|
|
13
|
+
return () => listeners.delete(listener);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
9
16
|
let set = newValue => {
|
|
10
17
|
const nextValue = typeof newValue === 'function' ? newValue(value) : newValue;
|
|
11
18
|
if (!Object.is(value, nextValue)) {
|
|
@@ -14,20 +21,14 @@ const createState = ({
|
|
|
14
21
|
listeners.forEach(listener => listener(nextValue, prevValue));
|
|
15
22
|
}
|
|
16
23
|
};
|
|
17
|
-
const subscribe = listener => {
|
|
18
|
-
listeners.add(listener);
|
|
19
|
-
return () => listeners.delete(listener);
|
|
20
|
-
};
|
|
21
24
|
if (middleware) set = middleware({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
sub: subscribe
|
|
25
|
+
...readonlyState,
|
|
26
|
+
set
|
|
25
27
|
}, config);
|
|
26
28
|
return {
|
|
27
29
|
...actionBuilder?.(set, get),
|
|
28
|
-
|
|
29
|
-
set
|
|
30
|
-
sub: subscribe
|
|
30
|
+
...readonlyState,
|
|
31
|
+
set
|
|
31
32
|
};
|
|
32
33
|
};
|
|
33
34
|
const state = /*#__PURE__*/createState();
|
|
@@ -7,26 +7,18 @@ const useSelector = (selectorParamFactory, deps) => {
|
|
|
7
7
|
const cutoff = items.length - 1;
|
|
8
8
|
const selectorFunc = items[cutoff];
|
|
9
9
|
items.length = cutoff;
|
|
10
|
-
const [context] = useState(() => (
|
|
11
|
-
sub: createSubscriber(items)
|
|
12
|
-
}));
|
|
13
|
-
const get = () => {
|
|
14
|
-
const {
|
|
15
|
-
cache
|
|
16
|
-
} = context;
|
|
17
|
-
const selectorValues = getSelectorValues(items);
|
|
18
|
-
const args = selectorValues.concat(deps || selectorFunc);
|
|
19
|
-
if (cache && isEqual(args, cache.args)) return cache.val;
|
|
20
|
-
const val = selectorFunc(...selectorValues);
|
|
21
|
-
context.cache = {
|
|
22
|
-
args,
|
|
23
|
-
val
|
|
24
|
-
};
|
|
25
|
-
return val;
|
|
26
|
-
};
|
|
10
|
+
const [context] = useState(() => [createSubscriber(items)]);
|
|
27
11
|
return useSnapshot({
|
|
28
|
-
get
|
|
29
|
-
|
|
12
|
+
get: () => {
|
|
13
|
+
const cache = context[1];
|
|
14
|
+
const selectorValues = getSelectorValues(items);
|
|
15
|
+
const args = selectorValues.concat(deps || selectorFunc);
|
|
16
|
+
if (cache && isEqual(args, cache[0])) return cache[1];
|
|
17
|
+
const val = selectorFunc(...selectorValues);
|
|
18
|
+
context[1] = [args, val];
|
|
19
|
+
return val;
|
|
20
|
+
},
|
|
21
|
+
subscribe: context[0]
|
|
30
22
|
});
|
|
31
23
|
};
|
|
32
24
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useSyncExternalStore } from './shim.mjs';
|
|
2
2
|
|
|
3
3
|
const useSnapshot = ({
|
|
4
|
-
|
|
4
|
+
subscribe,
|
|
5
5
|
get
|
|
6
6
|
}) => {
|
|
7
7
|
if (process.env.NODE_ENV !== 'production' && !useSyncExternalStore) {
|
|
8
8
|
throw new Error('[reactish-state] Shim setup is required for React 16/17. See: https://github.com/szhsin/reactish-state/tree/master?tab=readme-ov-file#react-1617-setup');
|
|
9
9
|
}
|
|
10
|
-
return useSyncExternalStore(
|
|
10
|
+
return useSyncExternalStore(subscribe, get, get);
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export { useSnapshot };
|
package/dist/esm/utils.mjs
CHANGED
|
@@ -5,7 +5,7 @@ const isEqual = (args1, args2) => {
|
|
|
5
5
|
return true;
|
|
6
6
|
};
|
|
7
7
|
const createSubscriber = items => listener => {
|
|
8
|
-
const unsubscribers = items.map(item => item.
|
|
8
|
+
const unsubscribers = items.map(item => item.subscribe(listener));
|
|
9
9
|
return () => unsubscribers.forEach(unsubscribe => unsubscribe());
|
|
10
10
|
};
|
|
11
11
|
const getSelectorValues = items => items.map(item => item.get());
|
|
@@ -14,15 +14,12 @@ const createSelector = ({
|
|
|
14
14
|
const selector = {
|
|
15
15
|
get: () => {
|
|
16
16
|
const args = getSelectorValues(items);
|
|
17
|
-
if (cache && isEqual(args, cache
|
|
17
|
+
if (cache && isEqual(args, cache[0])) return cache[1];
|
|
18
18
|
const val = selectorFunc(...args);
|
|
19
|
-
cache =
|
|
20
|
-
args,
|
|
21
|
-
val
|
|
22
|
-
};
|
|
19
|
+
cache = [args, val];
|
|
23
20
|
return val;
|
|
24
21
|
},
|
|
25
|
-
|
|
22
|
+
subscribe: createSubscriber(items)
|
|
26
23
|
};
|
|
27
24
|
plugin?.(selector, config);
|
|
28
25
|
return selector;
|
|
@@ -4,6 +4,13 @@ const createState = ({
|
|
|
4
4
|
let value = initialValue;
|
|
5
5
|
const listeners = new Set();
|
|
6
6
|
const get = () => value;
|
|
7
|
+
const readonlyState = {
|
|
8
|
+
get,
|
|
9
|
+
subscribe: listener => {
|
|
10
|
+
listeners.add(listener);
|
|
11
|
+
return () => listeners.delete(listener);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
7
14
|
let set = newValue => {
|
|
8
15
|
const nextValue = typeof newValue === 'function' ? newValue(value) : newValue;
|
|
9
16
|
if (!Object.is(value, nextValue)) {
|
|
@@ -12,20 +19,14 @@ const createState = ({
|
|
|
12
19
|
listeners.forEach(listener => listener(nextValue, prevValue));
|
|
13
20
|
}
|
|
14
21
|
};
|
|
15
|
-
const subscribe = listener => {
|
|
16
|
-
listeners.add(listener);
|
|
17
|
-
return () => listeners.delete(listener);
|
|
18
|
-
};
|
|
19
22
|
if (middleware) set = middleware({
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
sub: subscribe
|
|
23
|
+
...readonlyState,
|
|
24
|
+
set
|
|
23
25
|
}, config);
|
|
24
26
|
return {
|
|
25
27
|
...actionBuilder?.(set, get),
|
|
26
|
-
|
|
27
|
-
set
|
|
28
|
-
sub: subscribe
|
|
28
|
+
...readonlyState,
|
|
29
|
+
set
|
|
29
30
|
};
|
|
30
31
|
};
|
|
31
32
|
const state = /*#__PURE__*/createState();
|
|
@@ -11,7 +11,7 @@ const reduxDevtools = ({
|
|
|
11
11
|
const mergedState = {};
|
|
12
12
|
return ({
|
|
13
13
|
get,
|
|
14
|
-
|
|
14
|
+
subscribe
|
|
15
15
|
}, config) => {
|
|
16
16
|
const key = config?.key;
|
|
17
17
|
if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` plugin is used.');
|
|
@@ -9,7 +9,7 @@ const reduxDevtools = ({
|
|
|
9
9
|
const mergedState = {};
|
|
10
10
|
return ({
|
|
11
11
|
get,
|
|
12
|
-
|
|
12
|
+
subscribe
|
|
13
13
|
}, config) => {
|
|
14
14
|
const key = config?.key;
|
|
15
15
|
if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` plugin is used.');
|
package/package.json
CHANGED
package/types/types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type StateSubscriber<TValue> = (listener: StateListener<TValue>) => Unsub
|
|
|
6
6
|
export interface State<TValue, TContext = unknown> {
|
|
7
7
|
get: Getter<TValue>;
|
|
8
8
|
set: Setter<TValue, TContext>;
|
|
9
|
-
|
|
9
|
+
subscribe: StateSubscriber<TValue>;
|
|
10
10
|
}
|
|
11
11
|
export type StateWithAction<TValue, TAction, TContext = unknown> = Omit<TAction, keyof State<TValue, TContext>> & State<TValue, TContext>;
|
|
12
12
|
export type ActionBuilder<TValue, TAction, TContext = unknown> = (set: Setter<TValue, TContext>, get: () => TValue) => TAction;
|
|
@@ -20,7 +20,7 @@ export type SelectorListener = () => void;
|
|
|
20
20
|
export type SelectorSubscriber = (listener: SelectorListener) => Unsubscriber;
|
|
21
21
|
export interface Selector<TValue> {
|
|
22
22
|
get: Getter<TValue>;
|
|
23
|
-
|
|
23
|
+
subscribe: SelectorSubscriber;
|
|
24
24
|
}
|
|
25
25
|
export interface Config {
|
|
26
26
|
key?: string;
|