ccstate-react 4.11.0 → 4.12.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # ccstate-react
2
2
 
3
+ ## 4.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c8f4fca: fix(react): add global error handler for floating promises in useLoadable
8
+
9
+ ### Patch Changes
10
+
11
+ - ccstate@4.12.0
12
+
3
13
  ## 4.11.0
4
14
 
5
15
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -13,7 +13,8 @@ function useStore() {
13
13
  return store;
14
14
  }
15
15
 
16
- function useGet(atom) {
16
+ function useGetInternal(atom, _ref) {
17
+ var silenceUnhandleRejection = _ref.silenceUnhandleRejection;
17
18
  var store = useStore();
18
19
  return react.useSyncExternalStore(function (fn) {
19
20
  var ctrl = new AbortController();
@@ -24,7 +25,18 @@ function useGet(atom) {
24
25
  ctrl.abort();
25
26
  };
26
27
  }, function () {
27
- return store.get(atom);
28
+ var val = store.get(atom);
29
+ if (val instanceof Promise && silenceUnhandleRejection) {
30
+ val["catch"](function () {
31
+ return void 0;
32
+ });
33
+ }
34
+ return val;
35
+ });
36
+ }
37
+ function useGet(atom) {
38
+ return useGetInternal(atom, {
39
+ silenceUnhandleRejection: false
28
40
  });
29
41
  }
30
42
 
@@ -87,7 +99,9 @@ function _unsupportedIterableToArray(r, a) {
87
99
  }
88
100
 
89
101
  function useLoadableInternal(atom, keepLastResolved) {
90
- var promise = useGet(atom);
102
+ var promise = useGetInternal(atom, {
103
+ silenceUnhandleRejection: true
104
+ });
91
105
  var _useState = react.useState({
92
106
  state: 'loading'
93
107
  }),
package/dist/index.js CHANGED
@@ -11,7 +11,8 @@ function useStore() {
11
11
  return store;
12
12
  }
13
13
 
14
- function useGet(atom) {
14
+ function useGetInternal(atom, _ref) {
15
+ var silenceUnhandleRejection = _ref.silenceUnhandleRejection;
15
16
  var store = useStore();
16
17
  return useSyncExternalStore(function (fn) {
17
18
  var ctrl = new AbortController();
@@ -22,7 +23,18 @@ function useGet(atom) {
22
23
  ctrl.abort();
23
24
  };
24
25
  }, function () {
25
- return store.get(atom);
26
+ var val = store.get(atom);
27
+ if (val instanceof Promise && silenceUnhandleRejection) {
28
+ val["catch"](function () {
29
+ return void 0;
30
+ });
31
+ }
32
+ return val;
33
+ });
34
+ }
35
+ function useGet(atom) {
36
+ return useGetInternal(atom, {
37
+ silenceUnhandleRejection: false
26
38
  });
27
39
  }
28
40
 
@@ -85,7 +97,9 @@ function _unsupportedIterableToArray(r, a) {
85
97
  }
86
98
 
87
99
  function useLoadableInternal(atom, keepLastResolved) {
88
- var promise = useGet(atom);
100
+ var promise = useGetInternal(atom, {
101
+ silenceUnhandleRejection: true
102
+ });
89
103
  var _useState = useState({
90
104
  state: 'loading'
91
105
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccstate-react",
3
- "version": "4.11.0",
3
+ "version": "4.12.0",
4
4
  "description": "CCState React Hooks",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,7 +25,7 @@
25
25
  "react": ">=17.0.0"
26
26
  },
27
27
  "dependencies": {
28
- "ccstate": "^4.11.0"
28
+ "ccstate": "^4.12.0"
29
29
  },
30
30
  "peerDependenciesMeta": {
31
31
  "@types/react": {
@@ -55,7 +55,7 @@
55
55
  "shx": "^0.3.4",
56
56
  "signal-timers": "^1.0.4",
57
57
  "vitest": "^2.1.8",
58
- "ccstate": "^4.11.0"
58
+ "ccstate": "^4.12.0"
59
59
  },
60
60
  "scripts": {
61
61
  "build": "rollup -c",
@@ -3,7 +3,7 @@
3
3
  import '@testing-library/jest-dom/vitest';
4
4
  import { render, cleanup, screen } from '@testing-library/react';
5
5
  import userEvent from '@testing-library/user-event';
6
- import { afterEach, expect, it } from 'vitest';
6
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
7
7
  import { computed, createStore, state } from 'ccstate';
8
8
  import type { Computed, State } from 'ccstate';
9
9
  import { StrictMode, useEffect } from 'react';
@@ -543,3 +543,54 @@ it('useLoadable accept sync computed', async () => {
543
543
 
544
544
  expect(await screen.findByText('hasData')).toBeInTheDocument();
545
545
  });
546
+
547
+ describe('works with AbortError', () => {
548
+ let abortController: AbortController;
549
+ let promise: Promise<void>;
550
+
551
+ beforeEach(() => {
552
+ abortController = new AbortController();
553
+ });
554
+
555
+ afterEach(async () => {
556
+ abortController.abort();
557
+
558
+ try {
559
+ await promise;
560
+ } catch {}
561
+ });
562
+
563
+ it('should not throw abortError', () => {
564
+ const store = createStore();
565
+ const signal = abortController.signal;
566
+
567
+ promise = new Promise((_resolve, reject) => {
568
+ signal.addEventListener('abort', () => {
569
+ reject(signal.reason as Error);
570
+ });
571
+ });
572
+
573
+ const reload$ = state(0);
574
+ const promise$ = computed(async (get) => {
575
+ get(reload$);
576
+ await promise;
577
+ });
578
+
579
+ function App() {
580
+ useLoadable(promise$);
581
+
582
+ return <div>Test</div>;
583
+ }
584
+
585
+ render(
586
+ <StoreProvider value={store}>
587
+ <App />
588
+ </StoreProvider>,
589
+ );
590
+
591
+ expect(screen.getByText('Test')).toBeInTheDocument();
592
+
593
+ store.set(reload$, (x) => x + 1);
594
+ store.set(reload$, (x) => x + 1);
595
+ });
596
+ });
package/src/useGet.ts CHANGED
@@ -3,7 +3,10 @@ import { useStore } from './provider';
3
3
  import { command } from 'ccstate';
4
4
  import type { Computed, State } from 'ccstate';
5
5
 
6
- export function useGet<T>(atom: State<T> | Computed<T>) {
6
+ export function useGetInternal<T>(
7
+ atom: State<T> | Computed<T>,
8
+ { silenceUnhandleRejection }: { silenceUnhandleRejection: boolean },
9
+ ) {
7
10
  const store = useStore();
8
11
  return useSyncExternalStore(
9
12
  (fn) => {
@@ -14,7 +17,15 @@ export function useGet<T>(atom: State<T> | Computed<T>) {
14
17
  };
15
18
  },
16
19
  () => {
17
- return store.get(atom);
20
+ const val = store.get(atom);
21
+ if (val instanceof Promise && silenceUnhandleRejection) {
22
+ val.catch(() => void 0);
23
+ }
24
+ return val;
18
25
  },
19
26
  );
20
27
  }
28
+
29
+ export function useGet<T>(atom: State<T> | Computed<T>) {
30
+ return useGetInternal(atom, { silenceUnhandleRejection: false });
31
+ }
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from 'react';
2
- import { useGet } from './useGet';
2
+ import { useGetInternal } from './useGet';
3
3
  import type { Computed, State } from 'ccstate';
4
4
 
5
5
  type Loadable<T> =
@@ -19,7 +19,9 @@ function useLoadableInternal<T>(
19
19
  atom: State<Promise<T> | T> | Computed<Promise<T> | T>,
20
20
  keepLastResolved: boolean,
21
21
  ): Loadable<T> {
22
- const promise = useGet(atom);
22
+ const promise = useGetInternal(atom, {
23
+ silenceUnhandleRejection: true,
24
+ });
23
25
 
24
26
  const [promiseResult, setPromiseResult] = useState<Loadable<T>>({
25
27
  state: 'loading',