mirror of
https://github.com/re-rxjs/react-rxjs.git
synced 2025-12-08 18:01:51 +00:00
v0.2.0-alpha.8
This commit is contained in:
parent
1d5c8abf4d
commit
e750dd13b8
14
package-lock.json
generated
14
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@josepot/react-rxjs",
|
||||
"version": "0.2.0-alpha.7",
|
||||
"version": "0.2.0-alpha.8",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -1476,9 +1476,9 @@
|
||||
}
|
||||
},
|
||||
"@testing-library/react-hooks": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-3.2.1.tgz",
|
||||
"integrity": "sha512-1OB6Ksvlk6BCJA1xpj8/WWz0XVd1qRcgqdaFAq+xeC6l61Ucj0P6QpA5u+Db/x9gU4DCX8ziR5b66Mlfg0M2RA==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-3.3.0.tgz",
|
||||
"integrity": "sha512-rE9geI1+HJ6jqXkzzJ6abREbeud6bLF8OmF+Vyc7gBoPwZAEVBYjbC1up5nNoVfYBhO5HUwdD4u9mTehAUeiyw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.4",
|
||||
@ -9197,9 +9197,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz",
|
||||
"integrity": "sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==",
|
||||
"version": "3.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
|
||||
"integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
|
||||
"dev": true
|
||||
},
|
||||
"unicode-canonical-property-names-ecmascript": {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.2.0-alpha.7",
|
||||
"version": "0.2.0-alpha.8",
|
||||
"sideEffects": false,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -37,7 +37,7 @@
|
||||
"module": "dist/react-rxjs.esm.js",
|
||||
"devDependencies": {
|
||||
"@josepot/rxjs-utils": "^0.12.0",
|
||||
"@testing-library/react-hooks": "^3.2.1",
|
||||
"@testing-library/react-hooks": "^3.3.0",
|
||||
"@types/jest": "^25.2.3",
|
||||
"@types/react": "^16.9.35",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
@ -49,6 +49,6 @@
|
||||
"rxjs": "^6.5.5",
|
||||
"tsdx": "^0.13.2",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript": "^3.9.3"
|
||||
"typescript": "^3.9.5"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Observable, NEVER, concat } from "rxjs"
|
||||
import distinctShareReplay from "./operators/distinct-share-replay"
|
||||
import { FactoryObservableOptions, defaultFactoryOptions } from "./options"
|
||||
import useSharedReplayableObservable from "./useSharedReplayableObservable"
|
||||
import useObservable from "./useObservable"
|
||||
|
||||
export function connectFactoryObservable<
|
||||
I,
|
||||
@ -39,11 +39,7 @@ export function connectFactoryObservable<
|
||||
|
||||
return [
|
||||
(...input: A) =>
|
||||
useSharedReplayableObservable(
|
||||
getSharedObservable$(...input),
|
||||
initialValue,
|
||||
options,
|
||||
),
|
||||
useObservable(getSharedObservable$(...input), initialValue, options),
|
||||
|
||||
getSharedObservable$,
|
||||
]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Observable, NEVER, concat } from "rxjs"
|
||||
import distinctShareReplay from "./operators/distinct-share-replay"
|
||||
import { StaticObservableOptions, defaultStaticOptions } from "./options"
|
||||
import useSharedReplayableObservable from "./useSharedReplayableObservable"
|
||||
import useObservable from "./useObservable"
|
||||
|
||||
export function connectObservable<O, IO>(
|
||||
observable: Observable<O>,
|
||||
@ -18,7 +18,7 @@ export function connectObservable<O, IO>(
|
||||
)
|
||||
|
||||
const useStaticObservable = () =>
|
||||
useSharedReplayableObservable(sharedObservable$, initialValue, options)
|
||||
useObservable(sharedObservable$, initialValue, options)
|
||||
|
||||
return [useStaticObservable, sharedObservable$] as const
|
||||
}
|
||||
|
||||
@ -2,4 +2,4 @@ export { connectObservable } from "./connectObservable"
|
||||
export { connectFactoryObservable } from "./connectFactoryObservable"
|
||||
export { connectInstanceObservable } from "./connectInstanceObservable"
|
||||
export { default as distinctShareReplay } from "./operators/distinct-share-replay"
|
||||
export { default as useSharedReplayableObservable } from "./useSharedReplayableObservable"
|
||||
export { default as useObservable } from "./useObservable"
|
||||
|
||||
41
src/useObservable.ts
Normal file
41
src/useObservable.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { useState, useLayoutEffect } from "react"
|
||||
import { Observable } from "rxjs"
|
||||
import delayUnsubscription from "./operators/delay-unsubscription"
|
||||
import { defaultFactoryOptions, ObservableOptions } from "./options"
|
||||
|
||||
const useObservable = <O, I>(
|
||||
source$: Observable<O>,
|
||||
initialValue: I,
|
||||
options?: ObservableOptions,
|
||||
) => {
|
||||
const { suspenseTime, unsubscribeGraceTime } = {
|
||||
...defaultFactoryOptions,
|
||||
...options,
|
||||
}
|
||||
const [state, setState] = useState<I | O>(initialValue)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
let timeoutToken =
|
||||
suspenseTime === Infinity
|
||||
? undefined
|
||||
: setTimeout(setState, suspenseTime, initialValue)
|
||||
|
||||
const stopInitialState = () => {
|
||||
if (!timeoutToken) return
|
||||
timeoutToken = clearTimeout(timeoutToken) as undefined
|
||||
}
|
||||
|
||||
const subscription = delayUnsubscription(unsubscribeGraceTime)(
|
||||
source$,
|
||||
).subscribe(nextState => {
|
||||
setState(nextState as any)
|
||||
stopInitialState()
|
||||
})
|
||||
|
||||
return () => subscription.unsubscribe()
|
||||
}, [source$, suspenseTime, unsubscribeGraceTime])
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
export default useObservable
|
||||
@ -1,37 +0,0 @@
|
||||
import { useState, useLayoutEffect } from "react"
|
||||
import { Observable, of, race, concat } from "rxjs"
|
||||
import { delay } from "rxjs/operators"
|
||||
import delayUnsubscription from "./operators/delay-unsubscription"
|
||||
import { defaultFactoryOptions, ObservableOptions } from "./options"
|
||||
|
||||
const useSharedReplayableObservable = <O, I>(
|
||||
sharedReplayableObservable$: Observable<O>,
|
||||
initialValue: I,
|
||||
options?: ObservableOptions,
|
||||
) => {
|
||||
const { suspenseTime, unsubscribeGraceTime } = {
|
||||
...defaultFactoryOptions,
|
||||
...options,
|
||||
}
|
||||
const [state, setState] = useState<I | O>(initialValue)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const updates$ = sharedReplayableObservable$.pipe(
|
||||
delayUnsubscription(unsubscribeGraceTime),
|
||||
)
|
||||
|
||||
const subscription = (suspenseTime === Infinity
|
||||
? updates$
|
||||
: race(
|
||||
concat(of(initialValue).pipe(delay(suspenseTime)), updates$),
|
||||
updates$,
|
||||
)
|
||||
).subscribe(setState)
|
||||
|
||||
return () => subscription.unsubscribe()
|
||||
}, [sharedReplayableObservable$, suspenseTime, unsubscribeGraceTime])
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
export default useSharedReplayableObservable
|
||||
33
test/useObservable.test.ts
Normal file
33
test/useObservable.test.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { defer, from, of } from "rxjs"
|
||||
import { useObservable } from "../src"
|
||||
import { renderHook, act } from "@testing-library/react-hooks"
|
||||
import { concatMap, delay } from "rxjs/operators"
|
||||
|
||||
const wait = (ms: number) => new Promise(res => setTimeout(res, ms))
|
||||
|
||||
describe("useObservable", () => {
|
||||
it("works", async () => {
|
||||
let counter = 0
|
||||
const source$ = defer(() => {
|
||||
counter++
|
||||
return from([1, 2, 3, 4]).pipe(concatMap(x => of(x).pipe(delay(10))))
|
||||
})
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useObservable(source$, 0, {
|
||||
suspenseTime: 0,
|
||||
unsubscribeGraceTime: 0,
|
||||
}),
|
||||
)
|
||||
|
||||
expect(result.current).toEqual(0)
|
||||
expect(counter).toBe(1)
|
||||
|
||||
await act(async () => {
|
||||
await wait(50)
|
||||
})
|
||||
|
||||
expect(result.current).toEqual(4)
|
||||
expect(counter).toBe(1)
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user