reactish-state 1.1.1 → 1.2.1-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 +2 -6
- package/dist/cjs/react/useSelector.cjs +1 -1
- package/dist/cjs/react/useSnapshot.cjs +2 -2
- package/dist/cjs/utils.cjs +1 -1
- package/dist/cjs/vanilla/selector.cjs +1 -1
- package/dist/cjs/vanilla/state.cjs +2 -2
- package/dist/esm/react/useSelector.mjs +1 -1
- package/dist/esm/react/useSnapshot.mjs +2 -2
- package/dist/esm/utils.mjs +1 -1
- package/dist/esm/vanilla/selector.mjs +1 -1
- package/dist/esm/vanilla/state.mjs +2 -2
- package/dist/plugin/cjs/reduxDevtools.cjs +1 -1
- package/dist/plugin/esm/reduxDevtools.mjs +1 -1
- package/package.json +12 -12
- package/types/index.d.ts +1 -1
- package/types/middleware/applyMiddleware.d.ts +3 -3
- package/types/middleware/immer.d.ts +1 -1
- package/types/middleware/persist.d.ts +2 -2
- package/types/middleware/reduxDevtools.d.ts +2 -2
- package/types/plugin/applyPlugin.d.ts +2 -2
- package/types/plugin/reduxDevtools.d.ts +2 -2
- package/types/react/useSelector.d.ts +2 -2
- package/types/react/useSnapshot.d.ts +2 -2
- package/types/types.d.ts +46 -0
- package/types/utils.d.ts +1 -1
- package/types/vanilla/selector.d.ts +5 -5
- package/types/vanilla/state.d.ts +6 -7
- package/types/common.d.ts +0 -37
package/README.md
CHANGED
|
@@ -273,10 +273,8 @@ 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.
|
|
278
|
-
console.log(tripleSelector.get())
|
|
279
|
-
);
|
|
276
|
+
const unsub1 = countState.sub(() => console.log(countState.get()));
|
|
277
|
+
const unsub2 = tripleSelector.sub(() => console.log(tripleSelector.get()));
|
|
280
278
|
|
|
281
279
|
// Updating `countState` will trigger both listeners
|
|
282
280
|
countState.set(10);
|
|
@@ -648,8 +646,6 @@ const myTodos = state<string[], { add: (newTodo: string) => void }>(
|
|
|
648
646
|
);
|
|
649
647
|
```
|
|
650
648
|
|
|
651
|
-
However, if you choose this method, you need to specify the types for both the state value and actions.
|
|
652
|
-
|
|
653
649
|
# Examples
|
|
654
650
|
|
|
655
651
|
- Counter – [sandbox](https://codesandbox.io/p/sandbox/reactish-counter-z42qt7) | [source](https://github.com/szhsin/reactish-state/tree/master/examples/examples/counter)
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
var shim = require('./shim.cjs');
|
|
4
4
|
|
|
5
5
|
const useSnapshot = ({
|
|
6
|
-
|
|
6
|
+
sub,
|
|
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(sub, 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.sub(listener));
|
|
11
11
|
return () => unsubscribers.forEach(unsubscribe => unsubscribe());
|
|
12
12
|
};
|
|
13
13
|
const getSelectorValues = items => items.map(item => item.get());
|
|
@@ -21,13 +21,13 @@ const createState = ({
|
|
|
21
21
|
if (middleware) set = middleware({
|
|
22
22
|
set,
|
|
23
23
|
get,
|
|
24
|
-
subscribe
|
|
24
|
+
sub: subscribe
|
|
25
25
|
}, config);
|
|
26
26
|
return {
|
|
27
27
|
...actionBuilder?.(set, get),
|
|
28
28
|
get,
|
|
29
29
|
set,
|
|
30
|
-
subscribe
|
|
30
|
+
sub: subscribe
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
33
|
const state = /*#__PURE__*/createState();
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useSyncExternalStore } from './shim.mjs';
|
|
2
2
|
|
|
3
3
|
const useSnapshot = ({
|
|
4
|
-
|
|
4
|
+
sub,
|
|
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(sub, 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.sub(listener));
|
|
9
9
|
return () => unsubscribers.forEach(unsubscribe => unsubscribe());
|
|
10
10
|
};
|
|
11
11
|
const getSelectorValues = items => items.map(item => item.get());
|
|
@@ -19,13 +19,13 @@ const createState = ({
|
|
|
19
19
|
if (middleware) set = middleware({
|
|
20
20
|
set,
|
|
21
21
|
get,
|
|
22
|
-
subscribe
|
|
22
|
+
sub: subscribe
|
|
23
23
|
}, config);
|
|
24
24
|
return {
|
|
25
25
|
...actionBuilder?.(set, get),
|
|
26
26
|
get,
|
|
27
27
|
set,
|
|
28
|
-
subscribe
|
|
28
|
+
sub: subscribe
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
31
|
const state = /*#__PURE__*/createState();
|
|
@@ -11,7 +11,7 @@ const reduxDevtools = ({
|
|
|
11
11
|
const mergedState = {};
|
|
12
12
|
return ({
|
|
13
13
|
get,
|
|
14
|
-
subscribe
|
|
14
|
+
sub: 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
|
-
subscribe
|
|
12
|
+
sub: 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reactish-state",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.2.1-alpha.0",
|
|
4
4
|
"description": "Simple, decentralized (atomic) state management for React.",
|
|
5
5
|
"author": "Zheng Song",
|
|
6
6
|
"license": "MIT",
|
|
@@ -83,37 +83,37 @@
|
|
|
83
83
|
"use-sync-external-store": "^1.5.0"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@babel/core": "^7.28.
|
|
87
|
-
"@babel/preset-env": "^7.28.
|
|
86
|
+
"@babel/core": "^7.28.4",
|
|
87
|
+
"@babel/preset-env": "^7.28.3",
|
|
88
88
|
"@babel/preset-react": "^7.27.1",
|
|
89
89
|
"@babel/preset-typescript": "^7.27.1",
|
|
90
90
|
"@redux-devtools/extension": "^3.3.0",
|
|
91
91
|
"@rollup/plugin-babel": "^6.0.4",
|
|
92
92
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
93
93
|
"@rollup/plugin-replace": "^6.0.2",
|
|
94
|
-
"@testing-library/jest-dom": "^6.
|
|
94
|
+
"@testing-library/jest-dom": "^6.8.0",
|
|
95
95
|
"@testing-library/react": "^16.3.0",
|
|
96
96
|
"@types/jest": "^30.0.0",
|
|
97
|
-
"@types/react": "^19.1.
|
|
97
|
+
"@types/react": "^19.1.12",
|
|
98
98
|
"@types/use-sync-external-store": "^1.5.0",
|
|
99
99
|
"babel-plugin-pure-annotations": "^0.1.2",
|
|
100
100
|
"deplift": "^1.0.1",
|
|
101
|
-
"eslint": "^9.
|
|
101
|
+
"eslint": "^9.35.0",
|
|
102
102
|
"eslint-config-prettier": "^10.1.8",
|
|
103
103
|
"eslint-plugin-jest": "^29.0.1",
|
|
104
104
|
"eslint-plugin-react": "^7.37.5",
|
|
105
105
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
106
106
|
"eslint-plugin-react-hooks-addons": "^0.5.0",
|
|
107
107
|
"globals": "^16.3.0",
|
|
108
|
-
"immer": "^10.1.
|
|
109
|
-
"jest": "^30.
|
|
110
|
-
"jest-environment-jsdom": "^30.
|
|
108
|
+
"immer": "^10.1.3",
|
|
109
|
+
"jest": "^30.1.3",
|
|
110
|
+
"jest-environment-jsdom": "^30.1.2",
|
|
111
111
|
"npm-run-all": "^4.1.5",
|
|
112
112
|
"prettier": "^3.6.2",
|
|
113
113
|
"react": "^19.1.1",
|
|
114
114
|
"react-dom": "^19.1.1",
|
|
115
|
-
"rollup": "^4.
|
|
116
|
-
"typescript": "^5.
|
|
117
|
-
"typescript-eslint": "^8.
|
|
115
|
+
"rollup": "^4.50.1",
|
|
116
|
+
"typescript": "^5.9.2",
|
|
117
|
+
"typescript-eslint": "^8.42.0"
|
|
118
118
|
}
|
|
119
119
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Middleware } from '../
|
|
2
|
-
declare const applyMiddleware: (middlewares: (Middleware | undefined)[], options?: {
|
|
1
|
+
import type { Middleware } from '../types';
|
|
2
|
+
declare const applyMiddleware: <TConfig>(middlewares: (Middleware<TConfig> | undefined)[], options?: {
|
|
3
3
|
fromRight?: boolean;
|
|
4
|
-
}) => Middleware
|
|
4
|
+
}) => Middleware<TConfig>;
|
|
5
5
|
export { applyMiddleware };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Middleware } from '../
|
|
2
|
-
interface PersistMiddleware extends Middleware {
|
|
1
|
+
import type { Middleware, Config } from '../types';
|
|
2
|
+
interface PersistMiddleware extends Middleware<Config> {
|
|
3
3
|
hydrate(this: void): void;
|
|
4
4
|
}
|
|
5
5
|
type Persist = (options?: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Middleware } from '../
|
|
1
|
+
import type { Middleware, Config } from '../types';
|
|
2
2
|
type ReduxDevtools = (options?: {
|
|
3
3
|
name?: string;
|
|
4
|
-
}) => Middleware | undefined;
|
|
4
|
+
}) => Middleware<Config> | undefined;
|
|
5
5
|
declare const reduxDevtools: ReduxDevtools;
|
|
6
6
|
export type { ReduxDevtools };
|
|
7
7
|
export { reduxDevtools };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Plugin } from '../
|
|
2
|
-
declare const applyPlugin: (plugins: (Plugin | undefined)[]) => Plugin
|
|
1
|
+
import type { Plugin } from '../types';
|
|
2
|
+
declare const applyPlugin: <TConfig>(plugins: (Plugin<TConfig> | undefined)[]) => Plugin<TConfig>;
|
|
3
3
|
export { applyPlugin };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Plugin } from '../
|
|
1
|
+
import type { Plugin, Config } from '../types';
|
|
2
2
|
type ReduxDevtools = (options?: {
|
|
3
3
|
name?: string;
|
|
4
|
-
}) => Plugin | undefined;
|
|
4
|
+
}) => Plugin<Config> | undefined;
|
|
5
5
|
declare const reduxDevtools: ReduxDevtools;
|
|
6
6
|
export type { ReduxDevtools };
|
|
7
7
|
export { reduxDevtools };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { SelectorArray, SelectorParams } from '../
|
|
2
|
-
declare const useSelector: <TArray extends SelectorArray,
|
|
1
|
+
import type { SelectorArray, SelectorParams } from '../types';
|
|
2
|
+
declare const useSelector: <TArray extends SelectorArray, TValue>(selectorParamFactory: () => SelectorParams<TArray, TValue>, deps?: unknown[]) => TValue;
|
|
3
3
|
export { useSelector };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Selector } from '../
|
|
2
|
-
declare const useSnapshot: <
|
|
1
|
+
import type { Selector } from '../types';
|
|
2
|
+
declare const useSnapshot: <TValue>({ sub, get }: Selector<TValue>) => TValue;
|
|
3
3
|
export { useSnapshot };
|
package/types/types.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type Getter<TValue> = () => TValue;
|
|
2
|
+
export type Setter<TValue, TContext = unknown> = (newValue: TValue | ((value: TValue) => TValue), context?: TContext) => void;
|
|
3
|
+
export type Unsubscriber = () => void;
|
|
4
|
+
export type StateListener<TValue> = (nextValue: TValue, prevValue: TValue) => void;
|
|
5
|
+
export type StateSubscriber<TValue> = (listener: StateListener<TValue>) => Unsubscriber;
|
|
6
|
+
export interface State<TValue, TContext = unknown> {
|
|
7
|
+
get: Getter<TValue>;
|
|
8
|
+
set: Setter<TValue, TContext>;
|
|
9
|
+
sub: StateSubscriber<TValue>;
|
|
10
|
+
}
|
|
11
|
+
export type StateWithAction<TValue, TAction, TContext = unknown> = Omit<TAction, keyof State<TValue, TContext>> & State<TValue, TContext>;
|
|
12
|
+
export type ActionBuilder<TValue, TAction, TContext = unknown> = (set: Setter<TValue, TContext>, get: () => TValue) => TAction;
|
|
13
|
+
export interface StateBuilder<TConfig = unknown> {
|
|
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>;
|
|
18
|
+
}
|
|
19
|
+
export type SelectorListener = () => void;
|
|
20
|
+
export type SelectorSubscriber = (listener: SelectorListener) => Unsubscriber;
|
|
21
|
+
export interface Selector<TValue> {
|
|
22
|
+
get: Getter<TValue>;
|
|
23
|
+
sub: SelectorSubscriber;
|
|
24
|
+
}
|
|
25
|
+
export interface Config {
|
|
26
|
+
key?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface Middleware<TConfig = unknown> {
|
|
29
|
+
<TValue, TContext = unknown>(state: State<TValue, TContext>, config?: TConfig): Setter<TValue, TContext>;
|
|
30
|
+
}
|
|
31
|
+
export interface Plugin<TConfig = unknown> {
|
|
32
|
+
<TValue>(selector: Selector<TValue>, config?: TConfig): void;
|
|
33
|
+
}
|
|
34
|
+
export type SelectorArray = Selector<unknown>[];
|
|
35
|
+
export type SelectorValueArray<TArray extends SelectorArray> = {
|
|
36
|
+
[index in keyof TArray]: ReturnType<TArray[index]['get']>;
|
|
37
|
+
};
|
|
38
|
+
export type SelectorFunc<TArray extends SelectorArray, TValue> = (...args: SelectorValueArray<TArray>) => TValue;
|
|
39
|
+
export type SelectorParams<TArray extends SelectorArray, TValue> = [
|
|
40
|
+
...TArray,
|
|
41
|
+
SelectorFunc<TArray, TValue>
|
|
42
|
+
];
|
|
43
|
+
export interface SelectorBuilder<TConfig = unknown> {
|
|
44
|
+
<TArray extends SelectorArray, TValue>(...items: SelectorParams<TArray, TValue>): Selector<TValue>;
|
|
45
|
+
<TArray extends SelectorArray, TValue>(...items: [...SelectorParams<TArray, TValue>, TConfig]): Selector<TValue>;
|
|
46
|
+
}
|
package/types/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SelectorSubscriber, SelectorArray, SelectorValueArray } from './
|
|
1
|
+
import type { SelectorSubscriber, SelectorArray, SelectorValueArray } from './types';
|
|
2
2
|
export declare const isEqual: (args1: unknown[], args2: unknown[]) => boolean;
|
|
3
3
|
export declare const createSubscriber: (items: SelectorArray) => SelectorSubscriber;
|
|
4
4
|
export declare const getSelectorValues: <RA extends SelectorArray>(items: SelectorArray) => SelectorValueArray<RA>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Plugin, SelectorBuilder } from '../
|
|
2
|
-
declare const createSelector: ({ plugin }?: {
|
|
3
|
-
plugin?: Plugin
|
|
4
|
-
}) => SelectorBuilder
|
|
5
|
-
declare const selector: SelectorBuilder
|
|
1
|
+
import type { Plugin, SelectorBuilder } from '../types';
|
|
2
|
+
declare const createSelector: <TConfig>({ plugin }?: {
|
|
3
|
+
plugin?: Plugin<TConfig>;
|
|
4
|
+
}) => SelectorBuilder<TConfig>;
|
|
5
|
+
declare const selector: SelectorBuilder<unknown>;
|
|
6
6
|
export { selector, createSelector };
|
package/types/vanilla/state.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
declare const createState: ({ middleware }?: {
|
|
3
|
-
middleware?: Middleware
|
|
4
|
-
}) => <
|
|
5
|
-
declare const state: <
|
|
6
|
-
|
|
7
|
-
export { state, createState, type StateBuilder };
|
|
1
|
+
import type { StateBuilder, Middleware } from '../types';
|
|
2
|
+
declare const createState: <TConfig>({ middleware }?: {
|
|
3
|
+
middleware?: Middleware<TConfig>;
|
|
4
|
+
}) => StateBuilder<TConfig>;
|
|
5
|
+
declare const state: StateBuilder<unknown>;
|
|
6
|
+
export { state, createState };
|
package/types/common.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export type Getter<T> = () => T;
|
|
2
|
-
export type Setter<T> = (newValue: T | ((value: T) => T), context?: unknown) => void;
|
|
3
|
-
export type Unsubscriber = () => void;
|
|
4
|
-
export type StateListener<T> = (nextValue: T, prevValue: T) => void;
|
|
5
|
-
export type StateSubscriber<T> = (listener: StateListener<T>) => Unsubscriber;
|
|
6
|
-
export interface State<T> {
|
|
7
|
-
get: Getter<T>;
|
|
8
|
-
set: Setter<T>;
|
|
9
|
-
subscribe: StateSubscriber<T>;
|
|
10
|
-
}
|
|
11
|
-
export type ActionBuilder<T, A> = ((set: Setter<T>, get: () => T) => A) | null | undefined;
|
|
12
|
-
export type StateWithAction<T, A> = Omit<A, keyof State<T>> & State<T>;
|
|
13
|
-
export type SelectorListener = () => void;
|
|
14
|
-
export type SelectorSubscriber = (listener: SelectorListener) => Unsubscriber;
|
|
15
|
-
export interface Selector<T> {
|
|
16
|
-
get: Getter<T>;
|
|
17
|
-
subscribe: SelectorSubscriber;
|
|
18
|
-
}
|
|
19
|
-
export interface Config {
|
|
20
|
-
key?: string;
|
|
21
|
-
}
|
|
22
|
-
export interface Middleware {
|
|
23
|
-
<T>(state: State<T>, config?: Config): Setter<T>;
|
|
24
|
-
}
|
|
25
|
-
export interface Plugin {
|
|
26
|
-
<T>(selector: Selector<T>, config?: Config): void;
|
|
27
|
-
}
|
|
28
|
-
export type SelectorArray = Selector<unknown>[];
|
|
29
|
-
export type SelectorValueArray<TArray extends SelectorArray> = {
|
|
30
|
-
[index in keyof TArray]: ReturnType<TArray[index]['get']>;
|
|
31
|
-
};
|
|
32
|
-
export type SelectorFunc<TArray extends SelectorArray, T> = (...args: SelectorValueArray<TArray>) => T;
|
|
33
|
-
export type SelectorParams<TArray extends SelectorArray, T> = [...TArray, SelectorFunc<TArray, T>];
|
|
34
|
-
export interface SelectorBuilder {
|
|
35
|
-
<RA extends SelectorArray, T>(...items: SelectorParams<RA, T>): Selector<T>;
|
|
36
|
-
<RA extends SelectorArray, T>(...items: [...SelectorParams<RA, T>, Config]): Selector<T>;
|
|
37
|
-
}
|