diff --git a/packages/core/package.json b/packages/core/package.json index 616636b..3efcf93 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -48,5 +48,11 @@ "authors": [ "Josep M Sobrepere (https://github.com/josepot)", "Victor Oliva (https://github.com/voliva)" - ] + ], + "dependencies": { + "use-sync-external-store": "^1.0.0-rc.0" + }, + "devDependencies": { + "@types/use-sync-external-store": "^0.0.3" + } } diff --git a/packages/core/src/internal/BehaviorObservable.ts b/packages/core/src/internal/BehaviorObservable.ts index 22204f3..a320429 100644 --- a/packages/core/src/internal/BehaviorObservable.ts +++ b/packages/core/src/internal/BehaviorObservable.ts @@ -2,5 +2,4 @@ import { Observable, Subscription } from "rxjs" export interface BehaviorObservable extends Observable { gV: (subscription?: Subscription) => T - aH: any } diff --git a/packages/core/src/internal/share-latest.ts b/packages/core/src/internal/share-latest.ts index fb0fa2c..907e6fe 100644 --- a/packages/core/src/internal/share-latest.ts +++ b/packages/core/src/internal/share-latest.ts @@ -74,22 +74,10 @@ const shareLatest = ( } }) as BehaviorObservable - let error: any = EMPTY_VALUE - let timeoutToken: any result.gV = (outterSubscription?: Subscription): T => { - if (currentValue !== EMPTY_VALUE) { - return currentValue - } + if (currentValue !== EMPTY_VALUE) return currentValue if (defaultValue !== EMPTY_VALUE) return defaultValue - if (error !== EMPTY_VALUE) { - clearTimeout(timeoutToken) - timeoutToken = setTimeout(() => { - error = EMPTY_VALUE - }, 50) - throw error - } - if (!subscription) { if (!outterSubscription) throw new Error("Missing Subscribe") @@ -108,10 +96,6 @@ const shareLatest = ( throw (promise = new Promise((res, rej) => { const setError = (e: any) => { - error = e - timeoutToken = setTimeout(() => { - error = EMPTY_VALUE - }, 50) rej(e) promise = null } diff --git a/packages/core/src/internal/useObservable.ts b/packages/core/src/internal/useObservable.ts index 2298bde..ee63983 100644 --- a/packages/core/src/internal/useObservable.ts +++ b/packages/core/src/internal/useObservable.ts @@ -1,39 +1,42 @@ -import { useEffect, useState, useRef } from "react" +import { useSyncExternalStore } from "use-sync-external-store/shim" import { BehaviorObservable } from "../internal/BehaviorObservable" import { Subscription } from "rxjs" +import { useRef, useState } from "react" + +type VoidCb = () => void + +interface Ref { + args: [(cb: VoidCb) => VoidCb, () => T] + source$: BehaviorObservable +} export const useObservable = ( source$: BehaviorObservable, subscription?: Subscription, ): O => { - const [state, setState] = useState<[O, BehaviorObservable]>(() => [ - source$.gV(subscription), - source$, - ]) - const prevStateRef = useRef O)>(state[0]) + const [, setError] = useState() + const callbackRef = useRef>() - if (source$ !== state[1]) { - setState([source$.gV(subscription), source$]) + if (!callbackRef.current || callbackRef.current.source$ !== source$) { + callbackRef.current = { + source$, + args: [ + (next: () => void) => { + const subscription = source$.subscribe({ + next, + error: (e) => { + setError(() => { + throw e + }) + }, + }) + + return () => subscription.unsubscribe() + }, + () => source$.gV(subscription), + ], + } } - useEffect(() => { - const subscription = source$.subscribe({ - next: (value: O) => { - if (!Object.is(prevStateRef.current, value)) { - setState([(prevStateRef.current = value), source$]) - } - }, - error: (error: any) => { - setState(() => { - throw error - }) - }, - }) - - return () => { - subscription.unsubscribe() - } - }, [source$]) - - return state[0] + return useSyncExternalStore(...callbackRef.current!.args) } diff --git a/yarn.lock b/yarn.lock index 769ee9f..cb15af6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1382,6 +1382,11 @@ dependencies: "@types/jest" "*" +"@types/use-sync-external-store@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" + integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -4122,6 +4127,11 @@ universalify@^0.1.2: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +use-sync-external-store@^1.0.0-rc.0: + version "1.0.0-rc.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.0.0-rc.0.tgz#0d8fb7cbc31ddfb3ee01225f6b0a700cf59c449b" + integrity sha512-0U9Xlc2QDFzSGMB0DvcJQL0+DIdxDPJC7mnZlYFbl7wrSrPMcs89X5TVkNB6Dzg618m8lZop+U+J6ow3vq9RAQ== + v8-to-istanbul@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed"