diff --git a/package.json b/package.json index 95cdab2b88..ea2f08a10d 100644 --- a/package.json +++ b/package.json @@ -136,8 +136,8 @@ "react": ">= 16.8.0" }, "dependencies": { - "react-wonka": "^2.0.0", + "react-wonka": "^2.0.1", "scheduler": ">= 0.16.0", - "wonka": "^4.0.5" + "wonka": "^4.0.7" } } diff --git a/src/utils/toSuspenseSource.test.ts b/src/utils/toSuspenseSource.test.ts index 56c7e9ed50..b1c52ea93d 100644 --- a/src/utils/toSuspenseSource.test.ts +++ b/src/utils/toSuspenseSource.test.ts @@ -72,7 +72,9 @@ it('throws a promise that resolves when the source emits a value', () => { expect(promise).toBeInstanceOf(Promise); next('test'); - expect(result).toBe('test'); + + // The result came in asynchronously and the original source has ended + expect(result).toBe(undefined); return promise.then(resolved => { expect(resolved).toBe('test'); diff --git a/src/utils/toSuspenseSource.ts b/src/utils/toSuspenseSource.ts index a332fcc802..b7c6265acb 100644 --- a/src/utils/toSuspenseSource.ts +++ b/src/utils/toSuspenseSource.ts @@ -1,48 +1,20 @@ -import { pipe, make, onPush, onEnd, subscribe, Source } from 'wonka'; +import { pipe, share, onPush, toPromise, takeWhile, take, Source } from 'wonka'; /** This converts a Source to a suspense Source; It will forward the first result synchronously or throw a promise that resolves when the result becomes available */ -export const toSuspenseSource = (source: Source): Source => { - // Create a new Source from scratch so we have full control over the Source's lifecycle - return make(({ next, complete }) => { - let isCancelled = false; - let resolveSuspense: (value: T) => void; - let synchronousResult: undefined | T; +export const toSuspenseSource = (source: Source): Source => sink => { + const shared = share(source); + let hasResult = false; + let hasSuspended = false; - const { unsubscribe } = pipe( - source, - // The onPush and onEnd forward the underlying results as usual, so that when no - // suspense promise is thrown, the source behaves as it normally would - onPush(next), - onEnd(complete as any), - subscribe(value => { - // When this operation resolved synchronously assign the result to - // synchronousResult which will be picked up below - if (resolveSuspense === undefined) { - synchronousResult = value; - } else if (!isCancelled) { - // Otherwise resolve the thrown promise, - resolveSuspense(value); - // And end and teardown both sources, since suspense will abort the - // underlying rendering component anyway - complete(); - unsubscribe(); - } - }) - ); + pipe( + shared, + takeWhile(() => !hasSuspended), + onPush(() => (hasResult = true)) + )(sink); - // If we have a synchronous result, push it onto this source, which is synchronous - // otherwise throw a new promise which will resolve later - if (synchronousResult === undefined) { - throw new Promise(resolve => { - resolveSuspense = resolve; - }); - } - - // Since promises aren't cancellable we have a flag that prevents - // the thrown promise from resolving if this source is cancelled - return () => { - isCancelled = true; - unsubscribe(); - }; - }); + if (!hasResult) { + hasSuspended = true; + sink(0); /* End */ + throw pipe(shared, take(1), toPromise); + } }; diff --git a/yarn.lock b/yarn.lock index 1ac1bde9eb..ebfca61fce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4718,10 +4718,10 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.12.0: react-is "^16.8.6" scheduler "^0.18.0" -react-wonka@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-wonka/-/react-wonka-2.0.0.tgz#d62d87c9c93ec3e603ecf1582df3615aadc5c2e9" - integrity sha512-7q0CNBnSltRyzb61joCxKqVntHbRJRhP/WPxEx+zM8l9Yd+0IRevJuPG8iCamgrGphusX5xtEtd4yyX7qvRM1g== +react-wonka@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/react-wonka/-/react-wonka-2.0.1.tgz#75bdf03dbad8ceb8c1066216f635f05ce2b642a5" + integrity sha512-mM2UH2gnK5LLzaqVWd6JCLrB1vO3I4PN/sQZbjvzsjms4vSv+nKwelNUftM0KeC+LtTPC4GGsuxyu2XJnsCUTw== react@^16.12.0: version "16.12.0" @@ -5981,10 +5981,10 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -wonka@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.5.tgz#3384b90ed8c1e6e182d6e2fb18468c33ab94e0af" - integrity sha512-XKnzSpsk2UcPfyjecdc14b7LZSPeOEhYEs+/oAZ+gXV9BuYIcZC3hpapFi2DFHj1Bk38/npusgkiSD0+KdyCzQ== +wonka@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.7.tgz#b4934685bd2449367bd72ce7770bfe3e6cc8a68b" + integrity sha512-Uhyl2cgWCUksYtU0Jt8MSzKUqK4BVUrewWxnn1YlKL3Zco4sDcCUDkbgH0i762HJs1rtsq03cfzsCWxJKaDgVg== word-wrap@~1.2.3: version "1.2.3"