pocket-state 0.1.9 → 0.1.11
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 +25 -8
- package/package.json +1 -1
- package/src/globalState/store.ts +33 -25
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ Works seamlessly **inside React** with hooks or **outside React** with a simple
|
|
|
14
14
|
- 🔌 Framework-agnostic – Works in plain TS/JS and React.
|
|
15
15
|
- 🛠 Middleware – Logging, persistence, batching, devtools bridges, etc.
|
|
16
16
|
- 🔔 Event Emitter – Subscribe to store and custom events.
|
|
17
|
+
- ⚖️ EqualityFn – Custom comparator (shallow by default, can use deep/custom).
|
|
17
18
|
- ✅ TypeScript-first – Fully type-safe.
|
|
18
19
|
|
|
19
20
|
---
|
|
@@ -183,17 +184,33 @@ export function CounterComponent() {
|
|
|
183
184
|
|
|
184
185
|
---
|
|
185
186
|
|
|
186
|
-
##
|
|
187
|
+
## ⚖️ EqualityFn
|
|
187
188
|
|
|
188
|
-
|
|
189
|
+
By default, `createStore` uses a shallow equality function to detect changes.
|
|
190
|
+
You can override this by providing a custom comparator as the 3rd argument:
|
|
189
191
|
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
```ts
|
|
193
|
+
import {createStore} from 'pocket-state';
|
|
194
|
+
import deepEqual from 'fast-deep-equal';
|
|
195
|
+
|
|
196
|
+
interface State {
|
|
197
|
+
count: number;
|
|
198
|
+
nested: {a: number; b: number};
|
|
194
199
|
}
|
|
200
|
+
|
|
201
|
+
// shallow equality (default)
|
|
202
|
+
const store1 = createStore<State>({count: 0, nested: {a: 1, b: 2}});
|
|
203
|
+
|
|
204
|
+
// deep equality
|
|
205
|
+
const store2 = createStore<State>(
|
|
206
|
+
{count: 0, nested: {a: 1, b: 2}},
|
|
207
|
+
[],
|
|
208
|
+
deepEqual,
|
|
209
|
+
);
|
|
195
210
|
```
|
|
196
211
|
|
|
212
|
+
This is useful when working with nested state objects and you want to avoid unnecessary re-renders.
|
|
213
|
+
|
|
197
214
|
---
|
|
198
215
|
|
|
199
216
|
## 🧩 API Reference
|
|
@@ -224,6 +241,6 @@ Generates a custom hook for your store.
|
|
|
224
241
|
|
|
225
242
|
## 📜 License
|
|
226
243
|
|
|
227
|
-
MIT
|
|
244
|
+
MIT
|
|
228
245
|
|
|
229
|
-
keywords: pocket-state, state-management, react, react-native, typescript, hooks, store
|
|
246
|
+
keywords: pocket-state, state-management, react, react-native, typescript, hooks, store, equalityFn
|
package/package.json
CHANGED
package/src/globalState/store.ts
CHANGED
|
@@ -10,7 +10,12 @@ export function createStore<T>(
|
|
|
10
10
|
equalityFn?: (a: any, b: any) => boolean,
|
|
11
11
|
): Store<T> {
|
|
12
12
|
const emitter: IEventEmitter = new EventEmitter();
|
|
13
|
-
|
|
13
|
+
const _initialState = Array.isArray(initialState)
|
|
14
|
+
? (initialState as any).slice()
|
|
15
|
+
: initialState && typeof initialState === 'object'
|
|
16
|
+
? {...initialState}
|
|
17
|
+
: initialState;
|
|
18
|
+
let state = _initialState;
|
|
14
19
|
|
|
15
20
|
const areEqual = equalityFn ?? shallow;
|
|
16
21
|
|
|
@@ -35,7 +40,7 @@ export function createStore<T>(
|
|
|
35
40
|
);
|
|
36
41
|
|
|
37
42
|
const getValue = ((key?: keyof T) => {
|
|
38
|
-
if (
|
|
43
|
+
if (key === undefined) return state;
|
|
39
44
|
return state[key];
|
|
40
45
|
}) as UseStoreGet<T>;
|
|
41
46
|
|
|
@@ -70,18 +75,20 @@ export function createStore<T>(
|
|
|
70
75
|
function setValue(
|
|
71
76
|
patch: Partial<T> | ((state: T) => Partial<T> | Promise<Partial<T>>),
|
|
72
77
|
): void {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
let resolved = typeof patch === 'function' ? patch(state) : patch;
|
|
79
|
+
if (resolved instanceof Promise) {
|
|
80
|
+
resolved
|
|
81
|
+
.then(res => {
|
|
82
|
+
if (res && typeof res === 'object') {
|
|
83
|
+
setFn(res as Partial<T>);
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
.catch(error => console.warn('[store.setValue] patch error:', error));
|
|
87
|
+
} else {
|
|
88
|
+
if (resolved && typeof resolved === 'object') {
|
|
89
|
+
setFn(resolved as Partial<T>);
|
|
83
90
|
}
|
|
84
|
-
}
|
|
91
|
+
}
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
function setImmer(updater: (draft: Draft<T>) => void): void {
|
|
@@ -95,17 +102,17 @@ export function createStore<T>(
|
|
|
95
102
|
}
|
|
96
103
|
const delta = {} as Partial<T>;
|
|
97
104
|
let changed = false;
|
|
98
|
-
for (const k in nextState) {
|
|
99
|
-
const nv = nextState[k];
|
|
100
|
-
const ov = state[k];
|
|
105
|
+
for (const k in nextState as any) {
|
|
106
|
+
const nv = (nextState as any)[k];
|
|
107
|
+
const ov = (state as any)[k];
|
|
101
108
|
if (nv !== ov) {
|
|
102
|
-
delta[k] = nv;
|
|
109
|
+
(delta as any)[k] = nv;
|
|
103
110
|
changed = true;
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
|
-
for (const k in state) {
|
|
113
|
+
for (const k in state as any) {
|
|
107
114
|
if (!(k in (nextState as any))) {
|
|
108
|
-
delta[k] = undefined;
|
|
115
|
+
(delta as any)[k] = undefined;
|
|
109
116
|
changed = true;
|
|
110
117
|
}
|
|
111
118
|
}
|
|
@@ -150,22 +157,23 @@ export function createStore<T>(
|
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
function getInitialValue(): T {
|
|
153
|
-
if (Array.isArray(
|
|
154
|
-
return (
|
|
160
|
+
if (Array.isArray(_initialState)) {
|
|
161
|
+
return (_initialState as any).slice();
|
|
155
162
|
}
|
|
156
|
-
if (
|
|
157
|
-
return {...
|
|
163
|
+
if (_initialState && typeof _initialState === 'object') {
|
|
164
|
+
return {..._initialState};
|
|
158
165
|
}
|
|
159
|
-
return
|
|
166
|
+
return _initialState;
|
|
160
167
|
}
|
|
161
168
|
|
|
162
169
|
function isDirty() {
|
|
163
|
-
return !areEqual(state,
|
|
170
|
+
return !areEqual(state, _initialState);
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
function getNumberOfSubscriber() {
|
|
167
174
|
return emitter.getNumberOfSubscriber();
|
|
168
175
|
}
|
|
176
|
+
|
|
169
177
|
return {
|
|
170
178
|
getValue,
|
|
171
179
|
getInitialValue,
|