reactish-state 1.2.1-alpha.0 → 1.2.1-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.
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.sub(() => console.log(countState.get()));
277
- const unsub2 = tripleSelector.sub(() => console.log(tripleSelector.get()));
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,20 @@ 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(() =>
13
+ // eslint-disable-next-line no-sparse-arrays
14
+ [, utils.createSubscriber(items)]);
29
15
  return useSnapshot.useSnapshot({
30
- get,
31
- sub: context.sub
16
+ get: () => {
17
+ const [cache] = context;
18
+ const selectorValues = utils.getSelectorValues(items);
19
+ const args = selectorValues.concat(deps || selectorFunc);
20
+ if (cache && utils.isEqual(args, cache[0])) return cache[1];
21
+ const value = selectorFunc(...selectorValues);
22
+ context[0] = [args, value];
23
+ return value;
24
+ },
25
+ subscribe: context[1]
32
26
  });
33
27
  };
34
28
 
@@ -3,13 +3,13 @@
3
3
  var shim = require('./shim.cjs');
4
4
 
5
5
  const useSnapshot = ({
6
- sub,
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(sub, get, get);
12
+ return shim.useSyncExternalStore(subscribe, get, get);
13
13
  };
14
14
 
15
15
  exports.useSnapshot = useSnapshot;
@@ -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.sub(listener));
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());
@@ -5,9 +5,7 @@ var utils = require('../utils.cjs');
5
5
  const createSelector = ({
6
6
  plugin
7
7
  } = {}) => (...items) => {
8
- const {
9
- length
10
- } = items;
8
+ const length = items.length;
11
9
  const cutoff = typeof items[length - 1] === 'function' ? length - 1 : length - 2;
12
10
  const selectorFunc = items[cutoff];
13
11
  const config = items[cutoff + 1];
@@ -16,15 +14,12 @@ const createSelector = ({
16
14
  const selector = {
17
15
  get: () => {
18
16
  const args = utils.getSelectorValues(items);
19
- if (cache && utils.isEqual(args, cache.args)) return cache.val;
20
- const val = selectorFunc(...args);
21
- cache = {
22
- args,
23
- val
24
- };
25
- return val;
17
+ if (cache && utils.isEqual(args, cache[0])) return cache[1];
18
+ const value = selectorFunc(...args);
19
+ cache = [args, value];
20
+ return value;
26
21
  },
27
- sub: utils.createSubscriber(items)
22
+ subscribe: utils.createSubscriber(items)
28
23
  };
29
24
  plugin?.(selector, config);
30
25
  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
- set,
23
- get,
24
- sub: subscribe
25
+ ...readonlyState,
26
+ set
25
27
  }, config);
26
28
  return {
27
29
  ...actionBuilder?.(set, get),
28
- get,
29
- set,
30
- sub: subscribe
30
+ ...readonlyState,
31
+ set
31
32
  };
32
33
  };
33
34
  const state = /*#__PURE__*/createState();
@@ -7,26 +7,20 @@ 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(() =>
11
+ // eslint-disable-next-line no-sparse-arrays
12
+ [, createSubscriber(items)]);
27
13
  return useSnapshot({
28
- get,
29
- sub: context.sub
14
+ get: () => {
15
+ const [cache] = context;
16
+ const selectorValues = getSelectorValues(items);
17
+ const args = selectorValues.concat(deps || selectorFunc);
18
+ if (cache && isEqual(args, cache[0])) return cache[1];
19
+ const value = selectorFunc(...selectorValues);
20
+ context[0] = [args, value];
21
+ return value;
22
+ },
23
+ subscribe: context[1]
30
24
  });
31
25
  };
32
26
 
@@ -1,13 +1,13 @@
1
1
  import { useSyncExternalStore } from './shim.mjs';
2
2
 
3
3
  const useSnapshot = ({
4
- sub,
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(sub, get, get);
10
+ return useSyncExternalStore(subscribe, get, get);
11
11
  };
12
12
 
13
13
  export { useSnapshot };
@@ -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.sub(listener));
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());
@@ -3,9 +3,7 @@ import { createSubscriber, getSelectorValues, isEqual } from '../utils.mjs';
3
3
  const createSelector = ({
4
4
  plugin
5
5
  } = {}) => (...items) => {
6
- const {
7
- length
8
- } = items;
6
+ const length = items.length;
9
7
  const cutoff = typeof items[length - 1] === 'function' ? length - 1 : length - 2;
10
8
  const selectorFunc = items[cutoff];
11
9
  const config = items[cutoff + 1];
@@ -14,15 +12,12 @@ const createSelector = ({
14
12
  const selector = {
15
13
  get: () => {
16
14
  const args = getSelectorValues(items);
17
- if (cache && isEqual(args, cache.args)) return cache.val;
18
- const val = selectorFunc(...args);
19
- cache = {
20
- args,
21
- val
22
- };
23
- return val;
15
+ if (cache && isEqual(args, cache[0])) return cache[1];
16
+ const value = selectorFunc(...args);
17
+ cache = [args, value];
18
+ return value;
24
19
  },
25
- sub: createSubscriber(items)
20
+ subscribe: createSubscriber(items)
26
21
  };
27
22
  plugin?.(selector, config);
28
23
  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
- set,
21
- get,
22
- sub: subscribe
23
+ ...readonlyState,
24
+ set
23
25
  }, config);
24
26
  return {
25
27
  ...actionBuilder?.(set, get),
26
- get,
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
- sub: subscribe
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
- sub: subscribe
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactish-state",
3
- "version": "1.2.1-alpha.0",
3
+ "version": "1.2.1-alpha.2",
4
4
  "description": "Simple, decentralized (atomic) state management for React.",
5
5
  "author": "Zheng Song",
6
6
  "license": "MIT",
@@ -1,3 +1,3 @@
1
1
  import type { Selector } from '../types';
2
- declare const useSnapshot: <TValue>({ sub, get }: Selector<TValue>) => TValue;
2
+ declare const useSnapshot: <TValue>({ subscribe, get }: Selector<TValue>) => TValue;
3
3
  export { useSnapshot };
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
- sub: StateSubscriber<TValue>;
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
- sub: SelectorSubscriber;
23
+ subscribe: SelectorSubscriber;
24
24
  }
25
25
  export interface Config {
26
26
  key?: string;