yuustate 3.10.0 → 3.10.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.
@@ -350,7 +350,7 @@ export declare const createQuery: <TData, TVariable extends StoreKey = never, TE
350
350
  */
351
351
  initialDataIsStale?: boolean;
352
352
  } | {
353
- initialData?: never;
353
+ initialData?: never | undefined;
354
354
  initialDataIsStale?: never;
355
355
  })) => QueryState<TData, TError>) & {
356
356
  setState: (value: SetStateInput<QueryState<TData, TError>>) => void;
@@ -31,5 +31,5 @@ export declare const createStore: <TState extends Record<string, any>>(initialSt
31
31
  /**
32
32
  * Initial state used on first render (and will also update the store state right after that)
33
33
  */
34
- initialState?: Partial<TState>;
34
+ initialState?: Partial<TState> | undefined;
35
35
  }) => TState) & import("../vanilla.d.mts").StoreApi<TState>;
@@ -4,7 +4,6 @@ export declare const getValueByPath: (obj: any, path: Path) => any;
4
4
  export declare const isPrefixPath: (candidatePrefix: Path, targetPath: Path) => boolean;
5
5
  export declare const compressPaths: (paths: Path[]) => Path[];
6
6
  export declare const useStoreStateProxy: <TState extends Record<string, any>>(storeState: TState) => readonly [TState, import("react").RefObject<Path[]>];
7
- export declare const NO_INITIAL_VALUE: {};
8
7
  export declare const useStoreStateWithInitializer: <TState extends Record<string, any>>(store: StoreApi<TState>, initialState?: Partial<TState>) => readonly [TState, import("react").RefObject<WeakMap<StoreApi<TState>, number>>];
9
8
  /**
10
9
  * React hook for subscribing to a store using automatic dependency tracking.
@@ -29,6 +28,6 @@ export declare const useStoreStateWithInitializer: <TState extends Record<string
29
28
  * // Component will only re-render if `user.name` changes
30
29
  */
31
30
  export declare const useStoreState: <TState extends Record<string, any>>(store: StoreApi<TState>, options?: {
32
- initialState?: Partial<TState>;
31
+ initialState?: Partial<TState> | undefined;
33
32
  }) => TState;
34
33
  export {};
package/esm/react.mjs CHANGED
@@ -49,23 +49,35 @@ const useStoreStateProxy = (storeState) => {
49
49
  }, [storeState]);
50
50
  return [trackedState, usedPathsRef];
51
51
  };
52
- const NO_INITIAL_VALUE = {};
53
- const useStoreStateWithInitializer = (store, initialState = NO_INITIAL_VALUE) => {
52
+ const useStoreStateWithInitializer = (store, initialState) => {
54
53
  const initiatedAt = useRef(new WeakMap([[store, 0]]));
55
- useEffect(() => {
56
- if (initialState === NO_INITIAL_VALUE || initiatedAt.current.get(store)) return;
54
+ useIsomorphicLayoutEffect(() => {
55
+ if (initialState === void 0 || initiatedAt.current.get(store)) return;
57
56
  store.setState(initialState);
58
57
  initiatedAt.current.set(store, Date.now());
59
58
  }, [store, initialState]);
60
59
  const storeState = store.getState();
61
- const finalState = initialState === NO_INITIAL_VALUE || initiatedAt.current.get(store) ? storeState : { ...storeState, ...initialState };
60
+ const finalState = initialState === void 0 || initiatedAt.current.get(store) ? storeState : { ...storeState, ...initialState };
62
61
  return [finalState, initiatedAt];
63
62
  };
64
63
  const useStoreState = (store, options = {}) => {
65
64
  const [state] = useStoreStateWithInitializer(store, options.initialState);
66
65
  const [trackedState, usedPathsRef] = useStoreStateProxy(state);
67
- const snapshotRef = useRef(store.getState());
68
- const getSnapshot = () => snapshotRef.current;
66
+ const snapshotRef = useRef(state);
67
+ const getSnapshot = () => {
68
+ const prevState = snapshotRef.current;
69
+ const nextState = store.getState();
70
+ const paths = compressPaths(usedPathsRef.current);
71
+ for (const path of paths) {
72
+ const prevVal = getValueByPath(prevState, path);
73
+ const nextVal = getValueByPath(nextState, path);
74
+ if (!Object.is(prevVal, nextVal)) {
75
+ snapshotRef.current = nextState;
76
+ break;
77
+ }
78
+ }
79
+ return snapshotRef.current;
80
+ };
69
81
  useSyncExternalStore(
70
82
  useCallback(
71
83
  (onStoreChange) => {
@@ -426,14 +438,14 @@ const createQuery = (queryFn, options = {}) => {
426
438
  }
427
439
  const useStore = (options2 = {}) => {
428
440
  const {
429
- initialData = NO_INITIAL_VALUE,
441
+ initialData,
430
442
  initialDataIsStale = false,
431
443
  revalidateOnMount = true,
432
444
  keepPreviousData
433
445
  } = options2;
434
446
  const [storeState, initialDataInitiatedAt] = useStoreStateWithInitializer(
435
447
  store,
436
- initialData === NO_INITIAL_VALUE ? void 0 : {
448
+ initialData === void 0 ? void 0 : {
437
449
  state: "SUCCESS",
438
450
  isSuccess: true,
439
451
  data: initialData
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "yuustate",
3
3
  "description": "Lightweight unified state management for sync and async data.",
4
4
  "private": false,
5
- "version": "3.10.0",
5
+ "version": "3.10.2",
6
6
  "keywords": [
7
7
  "utilities",
8
8
  "store",
@@ -350,7 +350,7 @@ export declare const createQuery: <TData, TVariable extends StoreKey = never, TE
350
350
  */
351
351
  initialDataIsStale?: boolean;
352
352
  } | {
353
- initialData?: never;
353
+ initialData?: never | undefined;
354
354
  initialDataIsStale?: never;
355
355
  })) => QueryState<TData, TError>) & {
356
356
  setState: (value: SetStateInput<QueryState<TData, TError>>) => void;
@@ -31,5 +31,5 @@ export declare const createStore: <TState extends Record<string, any>>(initialSt
31
31
  /**
32
32
  * Initial state used on first render (and will also update the store state right after that)
33
33
  */
34
- initialState?: Partial<TState>;
34
+ initialState?: Partial<TState> | undefined;
35
35
  }) => TState) & import("../vanilla.ts").StoreApi<TState>;
@@ -4,7 +4,6 @@ export declare const getValueByPath: (obj: any, path: Path) => any;
4
4
  export declare const isPrefixPath: (candidatePrefix: Path, targetPath: Path) => boolean;
5
5
  export declare const compressPaths: (paths: Path[]) => Path[];
6
6
  export declare const useStoreStateProxy: <TState extends Record<string, any>>(storeState: TState) => readonly [TState, import("react").RefObject<Path[]>];
7
- export declare const NO_INITIAL_VALUE: {};
8
7
  export declare const useStoreStateWithInitializer: <TState extends Record<string, any>>(store: StoreApi<TState>, initialState?: Partial<TState>) => readonly [TState, import("react").RefObject<WeakMap<StoreApi<TState>, number>>];
9
8
  /**
10
9
  * React hook for subscribing to a store using automatic dependency tracking.
@@ -29,6 +28,6 @@ export declare const useStoreStateWithInitializer: <TState extends Record<string
29
28
  * // Component will only re-render if `user.name` changes
30
29
  */
31
30
  export declare const useStoreState: <TState extends Record<string, any>>(store: StoreApi<TState>, options?: {
32
- initialState?: Partial<TState>;
31
+ initialState?: Partial<TState> | undefined;
33
32
  }) => TState;
34
33
  export {};
package/react.js CHANGED
@@ -51,23 +51,35 @@ const useStoreStateProxy = (storeState) => {
51
51
  }, [storeState]);
52
52
  return [trackedState, usedPathsRef];
53
53
  };
54
- const NO_INITIAL_VALUE = {};
55
- const useStoreStateWithInitializer = (store, initialState = NO_INITIAL_VALUE) => {
54
+ const useStoreStateWithInitializer = (store, initialState) => {
56
55
  const initiatedAt = react.useRef(new WeakMap([[store, 0]]));
57
- react.useEffect(() => {
58
- if (initialState === NO_INITIAL_VALUE || initiatedAt.current.get(store)) return;
56
+ useIsomorphicLayoutEffect(() => {
57
+ if (initialState === void 0 || initiatedAt.current.get(store)) return;
59
58
  store.setState(initialState);
60
59
  initiatedAt.current.set(store, Date.now());
61
60
  }, [store, initialState]);
62
61
  const storeState = store.getState();
63
- const finalState = initialState === NO_INITIAL_VALUE || initiatedAt.current.get(store) ? storeState : { ...storeState, ...initialState };
62
+ const finalState = initialState === void 0 || initiatedAt.current.get(store) ? storeState : { ...storeState, ...initialState };
64
63
  return [finalState, initiatedAt];
65
64
  };
66
65
  const useStoreState = (store, options = {}) => {
67
66
  const [state] = useStoreStateWithInitializer(store, options.initialState);
68
67
  const [trackedState, usedPathsRef] = useStoreStateProxy(state);
69
- const snapshotRef = react.useRef(store.getState());
70
- const getSnapshot = () => snapshotRef.current;
68
+ const snapshotRef = react.useRef(state);
69
+ const getSnapshot = () => {
70
+ const prevState = snapshotRef.current;
71
+ const nextState = store.getState();
72
+ const paths = compressPaths(usedPathsRef.current);
73
+ for (const path of paths) {
74
+ const prevVal = getValueByPath(prevState, path);
75
+ const nextVal = getValueByPath(nextState, path);
76
+ if (!Object.is(prevVal, nextVal)) {
77
+ snapshotRef.current = nextState;
78
+ break;
79
+ }
80
+ }
81
+ return snapshotRef.current;
82
+ };
71
83
  react.useSyncExternalStore(
72
84
  react.useCallback(
73
85
  (onStoreChange) => {
@@ -428,14 +440,14 @@ const createQuery = (queryFn, options = {}) => {
428
440
  }
429
441
  const useStore = (options2 = {}) => {
430
442
  const {
431
- initialData = NO_INITIAL_VALUE,
443
+ initialData,
432
444
  initialDataIsStale = false,
433
445
  revalidateOnMount = true,
434
446
  keepPreviousData
435
447
  } = options2;
436
448
  const [storeState, initialDataInitiatedAt] = useStoreStateWithInitializer(
437
449
  store,
438
- initialData === NO_INITIAL_VALUE ? void 0 : {
450
+ initialData === void 0 ? void 0 : {
439
451
  state: "SUCCESS",
440
452
  isSuccess: true,
441
453
  data: initialData