floppy-disk 2.16.0 → 3.0.0-alpha.2

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.
Files changed (75) hide show
  1. package/README.md +0 -835
  2. package/esm/index.d.mts +1 -0
  3. package/esm/index.mjs +1 -0
  4. package/esm/react/create-mutation.d.mts +135 -0
  5. package/esm/react/create-query.d.mts +319 -0
  6. package/esm/react/create-store.d.mts +25 -0
  7. package/esm/react/create-stores.d.mts +32 -0
  8. package/esm/react/use-isomorphic-layout-effect.d.mts +6 -0
  9. package/esm/react/use-store.d.mts +18 -0
  10. package/esm/react.d.mts +6 -0
  11. package/esm/react.mjs +503 -0
  12. package/esm/vanilla/basic.d.mts +21 -0
  13. package/esm/vanilla/hash.d.mts +7 -0
  14. package/esm/vanilla/shallow.d.mts +6 -0
  15. package/esm/vanilla/store.d.mts +75 -0
  16. package/esm/vanilla.d.mts +4 -0
  17. package/esm/vanilla.mjs +109 -0
  18. package/index.d.ts +1 -0
  19. package/index.js +12 -0
  20. package/package.json +50 -45
  21. package/react/create-mutation.d.ts +135 -0
  22. package/react/create-query.d.ts +319 -0
  23. package/react/create-store.d.ts +25 -0
  24. package/react/create-stores.d.ts +32 -0
  25. package/react/use-isomorphic-layout-effect.d.ts +6 -0
  26. package/react/use-store.d.ts +18 -0
  27. package/{lib/index.d.ts → react.d.ts} +2 -4
  28. package/react.js +511 -0
  29. package/ts_version_4.5_and_above_is_required.d.ts +0 -0
  30. package/vanilla/basic.d.ts +21 -0
  31. package/vanilla/hash.d.ts +7 -0
  32. package/vanilla/shallow.d.ts +6 -0
  33. package/vanilla/store.d.ts +75 -0
  34. package/vanilla.d.ts +4 -0
  35. package/vanilla.js +118 -0
  36. package/esm/fetcher.d.ts +0 -27
  37. package/esm/fetcher.js +0 -95
  38. package/esm/index.d.ts +0 -8
  39. package/esm/index.js +0 -8
  40. package/esm/react/create-bi-direction-query.d.ts +0 -166
  41. package/esm/react/create-bi-direction-query.js +0 -74
  42. package/esm/react/create-mutation.d.ts +0 -39
  43. package/esm/react/create-mutation.js +0 -56
  44. package/esm/react/create-query.d.ts +0 -319
  45. package/esm/react/create-query.js +0 -434
  46. package/esm/react/create-store.d.ts +0 -51
  47. package/esm/react/create-store.js +0 -38
  48. package/esm/react/create-stores.d.ts +0 -77
  49. package/esm/react/create-stores.js +0 -125
  50. package/esm/react/with-context.d.ts +0 -5
  51. package/esm/react/with-context.js +0 -14
  52. package/esm/store.d.ts +0 -24
  53. package/esm/store.js +0 -51
  54. package/esm/utils.d.ts +0 -24
  55. package/esm/utils.js +0 -31
  56. package/lib/fetcher.d.ts +0 -27
  57. package/lib/fetcher.js +0 -99
  58. package/lib/index.js +0 -11
  59. package/lib/react/create-bi-direction-query.d.ts +0 -166
  60. package/lib/react/create-bi-direction-query.js +0 -78
  61. package/lib/react/create-mutation.d.ts +0 -39
  62. package/lib/react/create-mutation.js +0 -60
  63. package/lib/react/create-query.d.ts +0 -319
  64. package/lib/react/create-query.js +0 -438
  65. package/lib/react/create-store.d.ts +0 -51
  66. package/lib/react/create-store.js +0 -42
  67. package/lib/react/create-stores.d.ts +0 -77
  68. package/lib/react/create-stores.js +0 -130
  69. package/lib/react/with-context.d.ts +0 -5
  70. package/lib/react/with-context.js +0 -18
  71. package/lib/store.d.ts +0 -24
  72. package/lib/store.js +0 -55
  73. package/lib/utils.d.ts +0 -24
  74. package/lib/utils.js +0 -39
  75. package/utils/package.json +0 -6
@@ -1,434 +0,0 @@
1
- import { createElement, useState } from 'react';
2
- import { getValue, hasValue, identityFn, isClient, noop } from '../utils';
3
- import { createStores } from './create-stores';
4
- const INITIAL_QUERY_STATE = {
5
- isWaiting: false,
6
- isWaitingNextPage: false,
7
- status: 'loading',
8
- isLoading: true,
9
- isSuccess: false,
10
- isError: false,
11
- isRefetching: false,
12
- isRefetchError: false,
13
- isPreviousData: false,
14
- isOptimisticData: false,
15
- data: undefined,
16
- response: undefined,
17
- responseUpdatedAt: undefined,
18
- error: undefined,
19
- errorUpdatedAt: undefined,
20
- retryCount: 0,
21
- isGoingToRetry: false,
22
- pageParam: undefined,
23
- pageParams: [undefined],
24
- hasNextPage: false,
25
- retryNextPageCount: 0,
26
- isGoingToRetryNextPage: false,
27
- };
28
- const useQueryDefaultDeps = (state) => [
29
- state.data,
30
- state.error,
31
- state.isWaitingNextPage,
32
- state.hasNextPage,
33
- ];
34
- const fallbackComponent = () => null;
35
- /**
36
- * @see https://floppy-disk.vercel.app/docs/api#createquery
37
- */
38
- export const createQuery = (queryFn, options = {}) => {
39
- const defaultFetchOnWindowFocus = options.fetchOnMount ?? true;
40
- const defaultFetchOnReconnect = options.fetchOnMount ?? true;
41
- const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = 3000, // 3 seconds
42
- fetchOnMount = true, fetchOnWindowFocus = defaultFetchOnWindowFocus, fetchOnReconnect = defaultFetchOnReconnect, enabled = true, retry = 1, retryDelay = 2000, // 2 seconds
43
- keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError, onSettled = noop, cacheTime = 5 * 60 * 1000, refetchInterval = false, ...createStoresOptions } = options;
44
- const retryTimeoutId = new Map();
45
- const retryNextPageTimeoutId = new Map();
46
- const resetTimeoutId = new Map();
47
- const refetchIntervalTimeoutId = new Map();
48
- const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
49
- const useQuery = createStores(({ get, set, key: _key, keyHash }) => {
50
- const key = _key;
51
- const getRetryProps = (error, retryCount) => {
52
- const prevState = get();
53
- const maxRetryCount = getValue(retry, error, prevState) || 0;
54
- const delay = getValue(retryDelay, error, prevState) || 0;
55
- return { shouldRetry: retryCount < maxRetryCount, delay };
56
- };
57
- const forceFetch = () => new Promise((resolve) => {
58
- const state = get();
59
- const { isWaiting, isLoading, pageParams } = state;
60
- const responseAllPages = [];
61
- const newPageParams = [pageParams[0]];
62
- let pageParam = pageParams[0];
63
- clearTimeout(refetchIntervalTimeoutId.get(keyHash));
64
- if (isWaiting || !getValue(enabled, key))
65
- return resolve(state);
66
- if (isLoading)
67
- set({ isWaiting: true });
68
- else
69
- set({ isWaiting: true, isRefetching: true });
70
- const callQuery = (innerResolve = resolve) => {
71
- if (get().isGoingToRetry) {
72
- if (isLoading)
73
- set({ isGoingToRetry: false, isWaiting: true });
74
- else
75
- set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
76
- clearTimeout(retryTimeoutId.get(keyHash));
77
- }
78
- preventReplaceResponse.set(keyHash, false);
79
- const stateBeforeCallQuery = { ...get(), pageParam };
80
- queryFn(key, stateBeforeCallQuery)
81
- .then((response) => {
82
- if (preventReplaceResponse.get(keyHash)) {
83
- set({ isWaiting: false, isRefetching: false });
84
- return innerResolve(get());
85
- }
86
- responseAllPages.push(response);
87
- const newPageParam = getNextPageParam(response, responseAllPages.length, stateBeforeCallQuery);
88
- newPageParams.push(newPageParam);
89
- if (hasValue(newPageParam) && newPageParams.length < pageParams.length) {
90
- pageParam = newPageParam;
91
- callQuery();
92
- return;
93
- }
94
- const nextState = {
95
- isWaiting: false,
96
- status: 'success',
97
- isLoading: false,
98
- isSuccess: true,
99
- isError: false,
100
- isRefetching: false,
101
- isRefetchError: false,
102
- isPreviousData: false,
103
- isOptimisticData: false,
104
- data: responseAllPages.reduce((prev, responseCurrentPage) => {
105
- return select(responseCurrentPage, { key, data: prev });
106
- }, undefined),
107
- response,
108
- responseUpdatedAt: Date.now(),
109
- error: undefined,
110
- errorUpdatedAt: undefined,
111
- retryCount: 0,
112
- pageParam: newPageParam,
113
- pageParams: newPageParams,
114
- hasNextPage: hasValue(newPageParam),
115
- };
116
- const refetchIntervalValue = isClient && getValue(refetchInterval, { ...get(), ...nextState });
117
- if (refetchIntervalValue) {
118
- refetchIntervalTimeoutId.set(keyHash, window.setTimeout(() => {
119
- forceFetch();
120
- }, refetchIntervalValue));
121
- }
122
- set(nextState);
123
- onSuccess(response, stateBeforeCallQuery);
124
- onSettled(stateBeforeCallQuery);
125
- innerResolve(get());
126
- })
127
- .catch((error) => {
128
- const prevState = get();
129
- const errorUpdatedAt = Date.now();
130
- const { shouldRetry, delay } = getRetryProps(error, prevState.retryCount);
131
- if (shouldRetry) {
132
- set({
133
- isWaiting: false,
134
- isGoingToRetry: true,
135
- });
136
- if (isClient) {
137
- retryTimeoutId.set(keyHash, window.setTimeout(() => {
138
- set({ retryCount: prevState.retryCount + 1 });
139
- callQuery(innerResolve);
140
- }, delay));
141
- }
142
- return;
143
- }
144
- set(prevState.isSuccess && !prevState.isPreviousData
145
- ? {
146
- isWaiting: false,
147
- isRefetching: false,
148
- isRefetchError: true,
149
- data: responseAllPages.length
150
- ? responseAllPages.reduce((prev, response) => {
151
- return select(response, { key, data: prev });
152
- }, undefined)
153
- : prevState.data,
154
- error,
155
- errorUpdatedAt,
156
- pageParam,
157
- hasNextPage: hasValue(pageParam),
158
- }
159
- : {
160
- isWaiting: false,
161
- status: 'error',
162
- isLoading: false,
163
- isError: true,
164
- data: undefined,
165
- error,
166
- errorUpdatedAt,
167
- pageParam,
168
- hasNextPage: hasValue(pageParam),
169
- });
170
- if (onError)
171
- onError(error, stateBeforeCallQuery);
172
- else
173
- console.error(error, get());
174
- onSettled(stateBeforeCallQuery);
175
- innerResolve(get());
176
- });
177
- };
178
- callQuery();
179
- });
180
- const fetch = () => {
181
- const { responseUpdatedAt } = get();
182
- const isStale = !responseUpdatedAt || Date.now() > responseUpdatedAt + staleTime;
183
- if (!isStale)
184
- return;
185
- forceFetch();
186
- };
187
- const fetchNextPage = () => new Promise((resolve) => {
188
- const state = get();
189
- if (typeof options.getNextPageParam !== 'function') {
190
- console.warn('fetchNextPage with invalid getNextPageParam option');
191
- return resolve(state);
192
- }
193
- const { isLoading, isWaitingNextPage, data, hasNextPage, pageParam, pageParams } = state;
194
- if (isLoading)
195
- return resolve(forceFetch());
196
- if (isWaitingNextPage || !hasNextPage || !getValue(enabled, key))
197
- return resolve(state);
198
- set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
199
- clearTimeout(retryNextPageTimeoutId.get(keyHash));
200
- const stateBeforeCallQuery = get();
201
- queryFn(key, { ...state, pageParam })
202
- .then((response) => {
203
- if (preventReplaceResponse.get(keyHash)) {
204
- set({ isWaitingNextPage: false });
205
- return resolve(get());
206
- }
207
- const newPageParam = getNextPageParam(response, pageParams.length, stateBeforeCallQuery);
208
- set({
209
- isWaitingNextPage: false,
210
- response,
211
- responseUpdatedAt: Date.now(),
212
- data: select(response, { key, data }),
213
- pageParam: newPageParam,
214
- pageParams: pageParams.concat(newPageParam),
215
- hasNextPage: hasValue(newPageParam),
216
- });
217
- onSuccess(response, stateBeforeCallQuery);
218
- onSettled(stateBeforeCallQuery);
219
- resolve(get());
220
- })
221
- .catch((error) => {
222
- const prevState = get();
223
- const { shouldRetry, delay } = getRetryProps(error, prevState.retryNextPageCount);
224
- if (shouldRetry) {
225
- set({
226
- isWaitingNextPage: false,
227
- isGoingToRetryNextPage: true,
228
- });
229
- retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
230
- set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
231
- resolve(fetchNextPage());
232
- }, delay));
233
- return;
234
- }
235
- set({
236
- isWaitingNextPage: false,
237
- isError: true,
238
- error,
239
- errorUpdatedAt: Date.now(),
240
- });
241
- if (onError)
242
- onError(error, stateBeforeCallQuery);
243
- else
244
- console.error(error, get());
245
- onSettled(stateBeforeCallQuery);
246
- resolve(get());
247
- });
248
- });
249
- return {
250
- ...INITIAL_QUERY_STATE,
251
- key,
252
- keyHash,
253
- fetch,
254
- forceFetch,
255
- fetchNextPage,
256
- reset: () => {
257
- preventReplaceResponse.set(keyHash, true);
258
- clearTimeout(retryTimeoutId.get(keyHash));
259
- clearTimeout(retryNextPageTimeoutId.get(keyHash));
260
- set(INITIAL_QUERY_STATE);
261
- },
262
- optimisticUpdate: (response) => useQuery.optimisticUpdate({ key, response }),
263
- };
264
- }, (() => {
265
- const windowFocusHandler = () => {
266
- useQuery.getAllWithSubscriber().forEach((state) => {
267
- const result = getValue(fetchOnWindowFocus, state.key);
268
- if (result === 'always')
269
- state.forceFetch();
270
- else if (result)
271
- state.fetch();
272
- });
273
- };
274
- const reconnectHandler = () => {
275
- useQuery.getAllWithSubscriber().forEach((state) => {
276
- const result = getValue(fetchOnReconnect, state.key);
277
- if (result === 'always')
278
- state.forceFetch();
279
- else if (result)
280
- state.fetch();
281
- });
282
- };
283
- return {
284
- ...createStoresOptions,
285
- defaultDeps,
286
- onFirstSubscribe: (state) => {
287
- if (state.isSuccess) {
288
- const refetchIntervalValue = isClient && getValue(refetchInterval, state);
289
- if (refetchIntervalValue) {
290
- refetchIntervalTimeoutId.set(state.keyHash, window.setTimeout(() => {
291
- state.forceFetch();
292
- }, refetchIntervalValue));
293
- }
294
- }
295
- if (isClient) {
296
- if (fetchOnWindowFocus)
297
- window.addEventListener('focus', windowFocusHandler);
298
- if (fetchOnReconnect)
299
- window.addEventListener('online', reconnectHandler);
300
- }
301
- clearTimeout(resetTimeoutId.get(state.keyHash));
302
- onFirstSubscribe(state);
303
- },
304
- onSubscribe: (state) => {
305
- const result = getValue(fetchOnMount, state.key);
306
- if (result === 'always')
307
- state.forceFetch();
308
- else if (result)
309
- state.fetch();
310
- onSubscribe(state);
311
- },
312
- onLastUnsubscribe: (state) => {
313
- const totalSubs = useQuery.getAllWithSubscriber().length;
314
- if (isClient && totalSubs === 0) {
315
- if (fetchOnWindowFocus)
316
- window.removeEventListener('focus', windowFocusHandler);
317
- if (fetchOnReconnect)
318
- window.removeEventListener('online', reconnectHandler);
319
- }
320
- useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
321
- clearTimeout(retryTimeoutId.get(state.keyHash));
322
- clearTimeout(retryNextPageTimeoutId.get(state.keyHash));
323
- clearTimeout(refetchIntervalTimeoutId.get(state.keyHash));
324
- if (isClient && cacheTime !== Infinity) {
325
- resetTimeoutId.set(state.keyHash, window.setTimeout(() => {
326
- useQuery.set(state.key, INITIAL_QUERY_STATE);
327
- }, cacheTime));
328
- }
329
- onLastUnsubscribe(state);
330
- },
331
- onBeforeChangeKey: (nextKey, prevKey) => {
332
- if (keepPreviousData) {
333
- const nextData = useQuery.get(nextKey);
334
- if (!nextData.data) {
335
- const prevData = useQuery.get(prevKey);
336
- if (prevData.data) {
337
- useQuery.set(nextKey, {
338
- status: 'success',
339
- isLoading: false,
340
- isSuccess: true,
341
- isError: false,
342
- data: prevData.data,
343
- response: prevData.response,
344
- isPreviousData: true,
345
- }, true);
346
- }
347
- }
348
- }
349
- onBeforeChangeKey(nextKey, prevKey);
350
- },
351
- };
352
- })());
353
- useQuery.setInitialResponse = ({ key, response, skipRevalidation }) => {
354
- // eslint-disable-next-line react-hooks/rules-of-hooks
355
- useState(() => {
356
- const state = useQuery.get(key);
357
- if (response === undefined || state.isSuccess)
358
- return;
359
- const newPageParam = getNextPageParam(response, 1, state);
360
- useQuery.set(key, {
361
- status: 'success',
362
- isLoading: false,
363
- isSuccess: true,
364
- isError: false,
365
- response,
366
- responseUpdatedAt: skipRevalidation ? Date.now() : undefined,
367
- data: select(response, { key: key, data: undefined }),
368
- pageParam: newPageParam,
369
- pageParams: [undefined, newPageParam],
370
- hasNextPage: hasValue(newPageParam),
371
- });
372
- });
373
- };
374
- useQuery.reset = () => {
375
- useQuery.getStores().forEach((store, keyHash) => {
376
- preventReplaceResponse.set(keyHash, true);
377
- clearTimeout(retryTimeoutId.get(keyHash));
378
- clearTimeout(retryNextPageTimeoutId.get(keyHash));
379
- store.set(INITIAL_QUERY_STATE);
380
- });
381
- };
382
- useQuery.resetSpecificKey = (key) => useQuery.get(key).reset();
383
- useQuery.invalidate = () => {
384
- useQuery.getStores().forEach((store) => {
385
- const { get, set, getSubscribers } = store;
386
- set({ responseUpdatedAt: undefined });
387
- if (getSubscribers().size > 0)
388
- get().forceFetch();
389
- });
390
- };
391
- useQuery.invalidateSpecificKey = (key) => {
392
- const { get, set, getSubscribers } = useQuery.getStore(key);
393
- set({ responseUpdatedAt: undefined });
394
- if (getSubscribers().size > 0)
395
- get().forceFetch();
396
- };
397
- useQuery.optimisticUpdate = ({ key, response }) => {
398
- const prevState = useQuery.get(key);
399
- const optimisticResponse = getValue(response, prevState);
400
- useQuery.set(key, {
401
- isOptimisticData: true,
402
- response: optimisticResponse,
403
- data: select(optimisticResponse, { key: key, data: undefined }),
404
- });
405
- preventReplaceResponse.set(prevState.keyHash, true);
406
- const revert = () => {
407
- useQuery.set(key, {
408
- isOptimisticData: false,
409
- response: prevState.response,
410
- data: prevState.data,
411
- });
412
- };
413
- const invalidate = () => useQuery.invalidateSpecificKey(key);
414
- return { revert, invalidate };
415
- };
416
- useQuery.suspend = (key) => {
417
- // eslint-disable-next-line react-hooks/rules-of-hooks
418
- const state = useQuery(key);
419
- if (state.isLoading)
420
- throw state.forceFetch();
421
- if (state.isError)
422
- throw state.error;
423
- return state;
424
- };
425
- useQuery.Render = (props) => {
426
- const { queryKey, loading = fallbackComponent, success = fallbackComponent, error = fallbackComponent, } = props;
427
- // eslint-disable-next-line react-hooks/rules-of-hooks
428
- const state = useQuery(queryKey);
429
- if (state.data)
430
- return createElement(success, state);
431
- return createElement(state.isLoading ? loading : error, state);
432
- };
433
- return useQuery;
434
- };
@@ -1,51 +0,0 @@
1
- import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../store';
2
- export type WatchProps<T, K extends SelectDeps<T> | keyof T = SelectDeps<T>> = {
3
- selectDeps?: K;
4
- render: (state: K extends keyof T ? T[K] : T) => any;
5
- };
6
- export type UseStore<T extends StoreData> = {
7
- /**
8
- * @param selectDeps (Optional) A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
9
- * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
10
- *
11
- * Since version `2.13.0`, we can use a store's object key to control reactivity.
12
- *
13
- * **IMPORTANT NOTE:** `selectDeps` must not be changed after initialization.
14
- *
15
- * @example
16
- * ```tsx
17
- * const useMyStore = createStore({
18
- * foo: 12,
19
- * bar: true,
20
- * baz: "z",
21
- * });
22
- *
23
- * const MyComponent = () => {
24
- * const foo = useMyStore("foo");
25
- * // Will only re-render if "foo" updated
26
- * };
27
- * ```
28
- */
29
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(selectDeps?: K): K extends keyof T ? T[K] : T;
30
- get: () => T;
31
- set: (value: SetStoreData<T>, silent?: boolean) => void;
32
- subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
33
- getSubscribers: () => Subscribers<T>;
34
- /**
35
- * ⚛️ (**_Hook_**)
36
- *
37
- * Set default values **inside of a component**.
38
- *
39
- * **IMPORTANT NOTE:**
40
- * - This is a hook, put it inside of a React component
41
- * - Put this on the root component or parent component, before any component subscribed!
42
- */
43
- setDefaultValues: (values: SetStoreData<T>) => void;
44
- Watch: <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(props: WatchProps<T, K>) => any;
45
- };
46
- /**
47
- * @see https://floppy-disk.vercel.app/docs/api#createstore
48
- */
49
- export declare const createStore: <T extends StoreData>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T> & {
50
- defaultDeps?: SelectDeps<T>;
51
- }) => UseStore<T>;
@@ -1,38 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
- import { initStore, } from '../store';
3
- /**
4
- * @see https://floppy-disk.vercel.app/docs/api#createstore
5
- */
6
- export const createStore = (initializer, options = {}) => {
7
- const { get, set, subscribe, getSubscribers } = initStore(initializer, options);
8
- const { defaultDeps } = options;
9
- /**
10
- * **IMPORTANT NOTE:** `selectDeps` function must not be changed after initialization.
11
- */
12
- const useStore = (selectDeps = defaultDeps) => {
13
- const [state, setState] = useState(get);
14
- // eslint-disable-next-line react-hooks/exhaustive-deps
15
- useEffect(() => subscribe(setState, selectDeps), []);
16
- return (typeof selectDeps === 'string' ? state[selectDeps] : state);
17
- };
18
- useStore.get = get;
19
- useStore.set = set;
20
- useStore.subscribe = subscribe;
21
- useStore.getSubscribers = getSubscribers;
22
- useStore.setDefaultValues = (value) => {
23
- // eslint-disable-next-line react-hooks/rules-of-hooks
24
- useState(() => {
25
- const subscribers = getSubscribers();
26
- if (subscribers.size > 0) {
27
- console.warn('Put setDefaultValues on the root component or parent component, before any component subscribed!');
28
- }
29
- set(value);
30
- });
31
- };
32
- const Watch = ({ selectDeps = defaultDeps, render, }) => {
33
- const store = useStore(selectDeps);
34
- return render(store);
35
- };
36
- useStore.Watch = Watch;
37
- return useStore;
38
- };
@@ -1,77 +0,0 @@
1
- import { InitStoreOptions, InitStoreReturn, SelectDeps, SetStoreData, StoreData, Subscribers } from '../store';
2
- import { Maybe } from '../utils';
3
- import { WatchProps } from './create-store';
4
- export type StoreKey = Record<string, any> | undefined;
5
- export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = T | ((api: {
6
- get: () => T;
7
- set: (value: SetStoreData<T>, silent?: boolean) => void;
8
- key: TKey;
9
- keyHash: string;
10
- }) => T);
11
- export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
12
- /**
13
- * @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
14
- * No need to memoize the store key.
15
- *
16
- * @param selectDeps (Optional) A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
17
- * Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStores`.
18
- *
19
- * Since version `2.13.0`, we can use a store's object key to control reactivity.
20
- *
21
- * **IMPORTANT NOTE:** `selectDeps` must not be changed after initialization.
22
- *
23
- * @example
24
- * ```tsx
25
- * type StoreKey = { id: string };
26
- * type StoreData = { foo: number; bar: boolean; baz: string };
27
- * const useMyStores = createStores<StoreKey, StoreData>({
28
- * foo: 12,
29
- * bar: true,
30
- * baz: "z",
31
- * });
32
- *
33
- * export const MyComponent = () => {
34
- * const foo = useMyStores({ id: "p1" }, "foo");
35
- * // Will only re-render if "foo" & store key ("id") updated
36
- * };
37
- * ```
38
- */
39
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(selectDeps?: K): K extends keyof T ? T[K] : T;
40
- <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(key: Maybe<TKey>, selectDeps?: K): K extends keyof T ? T[K] : T;
41
- get: (key?: Maybe<TKey>) => T;
42
- getAll: () => T[];
43
- getAllWithSubscriber: () => T[];
44
- set: (key: Maybe<TKey>, value: SetStoreData<T>, silent?: boolean) => void;
45
- setAll: (value: SetStoreData<T>, silent?: boolean) => void;
46
- subscribe: (key: Maybe<TKey>, fn: (state: T) => void, selectDeps?: SelectDeps<T> | keyof T) => () => void;
47
- getSubscribers: (key: Maybe<TKey>) => Subscribers<T>;
48
- getStore: (key?: Maybe<TKey>) => InitStoreReturn<T>;
49
- getStores: () => Map<string, InitStoreReturn<T>>;
50
- /**
51
- * ⚛️ (**_Hook_**)
52
- *
53
- * Set default values **inside of a component**.
54
- *
55
- * **IMPORTANT NOTE:**
56
- * - This is a hook, put it inside of a React component
57
- * - Put this on the root component or parent component, before any component subscribed!
58
- */
59
- setDefaultValues: (key: Maybe<TKey>, values: SetStoreData<T>) => void;
60
- Watch: <K extends SelectDeps<T> | keyof T = SelectDeps<T>>(props: WatchProps<T, K> & {
61
- storeKey?: Maybe<TKey>;
62
- }) => any;
63
- };
64
- export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
65
- onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
66
- /**
67
- * Will be triggered when a single store with a specific key was initialized.
68
- */
69
- onStoreInitialized?: (key: TKey, keyHash: string) => void;
70
- defaultDeps?: SelectDeps<T>;
71
- hashKeyFn?: (obj: TKey) => string;
72
- };
73
- export declare const hashStoreKey: (value?: any) => string;
74
- /**
75
- * @see https://floppy-disk.vercel.app/docs/api#createstores
76
- */
77
- export declare const createStores: <TKey extends StoreKey = StoreKey, T extends StoreData = StoreData>(initializer: StoresInitializer<TKey, T>, options?: CreateStoresOptions<TKey, T>) => UseStores<TKey, T>;