extra-react-store 0.2.9 → 0.2.10

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.
@@ -1,7 +1,8 @@
1
- import { useCallback, useRef, useSyncExternalStore } from 'react';
2
- import { useIIFE, useStrictContext } from 'extra-react-hooks';
1
+ import { useRef } from 'react';
2
+ import { useIIFE, useForceUpdate, useStrictContext } from 'extra-react-hooks';
3
3
  import { isReferenceEqual } from 'extra-utils';
4
4
  export function useSelector(context, selector, isEqual = isReferenceEqual) {
5
+ const forceUpdate = useForceUpdate();
5
6
  const store = useStrictContext(context);
6
7
  const updateRequireRef = useRef(true);
7
8
  useIIFE(() => {
@@ -14,22 +15,22 @@ export function useSelector(context, selector, isEqual = isReferenceEqual) {
14
15
  valueRef.current = selector(store.getState());
15
16
  updateRequireRef.current = false;
16
17
  }
17
- const getSnapshot = useCallback(() => valueRef.current, [valueRef]);
18
- return useSyncExternalStore(useCallback((onStoreChange) => {
18
+ useIIFE(() => {
19
19
  return store.subscribe(state => {
20
20
  try {
21
21
  const newValue = selector(state);
22
22
  if (!isEqual(valueRef.current, newValue)) {
23
23
  valueRef.current = newValue;
24
24
  updateRequireRef.current = false;
25
- onStoreChange();
25
+ forceUpdate();
26
26
  }
27
27
  }
28
28
  catch {
29
29
  updateRequireRef.current = true;
30
- onStoreChange();
30
+ forceUpdate();
31
31
  }
32
32
  });
33
- }, [store, selector, isEqual, updateRequireRef, valueRef]), getSnapshot, getSnapshot);
33
+ }, [store, selector, isEqual, forceUpdate, valueRef, updateRequireRef]);
34
+ return valueRef.current;
34
35
  }
35
36
  //# sourceMappingURL=use-selector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-selector.js","sourceRoot":"","sources":["../src/use-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAE7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,MAAM,UAAU,WAAW,CACzB,OAA4B,EAC5B,QAAiC,EACjC,UAA2C,gBAAgB;IAE3D,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEvC,MAAM,gBAAgB,GAAG,MAAM,CAAU,IAAI,CAAC,CAAA;IAC9C,OAAO,CAAC,GAAG,EAAE;QACX,OAAO,GAAG,EAAE;YACV,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;QACjC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,QAAQ,GAAG,MAAM,CAAQ,SAAS,CAAC,CAAA;IACzC,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC7B,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC7C,gBAAgB,CAAC,OAAO,GAAG,KAAK,CAAA;IAClC,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IACpE,OAAO,oBAAoB,CACzB,WAAW,CAAC,CAAC,aAAyB,EAAE,EAAE;QACxC,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;YAC7B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;gBAEhC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;oBAC1C,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAA;oBAC3B,gBAAgB,CAAC,OAAO,GAAG,KAAK,CAAA;oBAChC,aAAa,EAAE,CAAA;gBACjB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;gBAC/B,aAAa,EAAE,CAAA;YACjB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC,EAC1D,WAAW,EACX,WAAW,CACZ,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"use-selector.js","sourceRoot":"","sources":["../src/use-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAE7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,MAAM,UAAU,WAAW,CACzB,OAA4B,EAC5B,QAAiC,EACjC,UAA2C,gBAAgB;IAY3D,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IACpC,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAEvC,MAAM,gBAAgB,GAAG,MAAM,CAAU,IAAI,CAAC,CAAA;IAC9C,OAAO,CAAC,GAAG,EAAE;QACX,OAAO,GAAG,EAAE;YACV,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;QACjC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,QAAQ,GAAG,MAAM,CAAQ,SAAS,CAAC,CAAA;IACzC,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC7B,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC7C,gBAAgB,CAAC,OAAO,GAAG,KAAK,CAAA;IAClC,CAAC;IAED,OAAO,CAAC,GAAG,EAAE;QACX,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;YAC7B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;gBAEhC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;oBAC1C,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAA;oBAC3B,gBAAgB,CAAC,OAAO,GAAG,KAAK,CAAA;oBAChC,WAAW,EAAE,CAAA;gBACf,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;gBAC/B,WAAW,EAAE,CAAA;YACf,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAA;IAEvE,OAAO,QAAQ,CAAC,OAAQ,CAAA;AAC1B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "extra-react-store",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "files": [
@@ -1,5 +1,5 @@
1
- import { useCallback, useRef, useSyncExternalStore } from 'react'
2
- import { useIIFE, useStrictContext } from 'extra-react-hooks'
1
+ import { useRef } from 'react'
2
+ import { useIIFE, useForceUpdate, useStrictContext } from 'extra-react-hooks'
3
3
  import { StoreContext } from './types.js'
4
4
  import { isReferenceEqual } from 'extra-utils'
5
5
 
@@ -8,6 +8,17 @@ export function useSelector<State, Value>(
8
8
  , selector: (state: State) => Value
9
9
  , isEqual: (a: Value, b: Value) => boolean = isReferenceEqual
10
10
  ): Value {
11
+ // 可以用React 18的useSyncExternalStore, 但毫无必要:
12
+ // - useSyncExternalStore的实现比现有实现的性能差.
13
+ // - useSyncExternalStore的实现包含现有实现的一部分功能, 但不支持自定义isEqual.
14
+ // 为了支持isEqual, useSelector需要重复一部分useSyncExternalStore逻辑, 完全是白费功夫.
15
+ // - useSyncExternalStore在内部也使用setState, 而且实现方式比useForceUpdate差.
16
+ // 这导致useSyncExternalStore不仅性能差,
17
+ // 还共享了useForceUpdate的全部弊端(渲染时跨组件setState会报错).
18
+ // - useSyncExternalStore为了支持SSR需要额外提供一个getServerSnapshot.
19
+ // 但对于一个状态管理库而言, getSnapshot和getServerSnapshot必然是等价的, 毫无区分的必要性.
20
+
21
+ const forceUpdate = useForceUpdate()
11
22
  const store = useStrictContext(context)
12
23
 
13
24
  const updateRequireRef = useRef<boolean>(true)
@@ -23,25 +34,22 @@ export function useSelector<State, Value>(
23
34
  updateRequireRef.current = false
24
35
  }
25
36
 
26
- const getSnapshot = useCallback(() => valueRef.current!, [valueRef])
27
- return useSyncExternalStore(
28
- useCallback((onStoreChange: () => void) => {
29
- return store.subscribe(state => {
30
- try {
31
- const newValue = selector(state)
37
+ useIIFE(() => {
38
+ return store.subscribe(state => {
39
+ try {
40
+ const newValue = selector(state)
32
41
 
33
- if (!isEqual(valueRef.current!, newValue)) {
34
- valueRef.current = newValue
35
- updateRequireRef.current = false
36
- onStoreChange()
37
- }
38
- } catch {
39
- updateRequireRef.current = true
40
- onStoreChange()
42
+ if (!isEqual(valueRef.current!, newValue)) {
43
+ valueRef.current = newValue
44
+ updateRequireRef.current = false
45
+ forceUpdate()
41
46
  }
42
- })
43
- }, [store, selector, isEqual, updateRequireRef, valueRef])
44
- , getSnapshot
45
- , getSnapshot
46
- )
47
+ } catch {
48
+ updateRequireRef.current = true
49
+ forceUpdate()
50
+ }
51
+ })
52
+ }, [store, selector, isEqual, forceUpdate, valueRef, updateRequireRef])
53
+
54
+ return valueRef.current!
47
55
  }