@@ -77,11 +77,13 @@ function App() {
7777### ` useObservable `
7878
7979``` tsx
80- declare function useObservable<T >(sourceFactory : () => Observable <T >): T | null
80+ declare type InputFactory <T , U = undefined > = U extends undefined
81+ ? (state$ : Observable <T >) => Observable <T >
82+ : (inputs$ : Observable <U >, state$ : Observable <T >) => Observable <T >
8183
82- declare function useObservable<T >(sourceFactory : () => Observable <T >, initialState : T ): T
83-
84- declare function useObservable<T , U >(sourceFactory : ( inputs$ : Observable < U >) => Observable < T >, initialState : T , inputs : U ): T
84+ declare function useObservable<T >(inputFactory : InputFactory <T >): T | null
85+ declare function useObservable< T >( inputFactory : InputFactory < T >, initialState : T ) : T
86+ declare function useObservable<T , U >(inputFactory : InputFactory < T , U >, initialState : T , inputs : U ): T
8587```
8688
8789#### Examples :
@@ -147,24 +149,62 @@ ReactDOM.render(<App foo={1000} />, document.querySelector('#app'))
147149ReactDOM.render(<App foo={2000} />, document.querySelector('#app'))
148150` ` `
149151
152+ ** useObservable with state$ **
153+
154+ [live demo ](https :// codesandbox.io/s/7jwv36w876)
155+
156+ ` ` ` tsx
157+ import React from 'react'
158+ import ReactDOM from 'react-dom'
159+ import { useObservable } from 'rxjs-hooks'
160+ import { interval } from 'rxjs'
161+ import { map, withLatestFrom } from 'rxjs/operators'
162+
163+ function App() {
164+ const value = useObservable((state$) => interval(1000).pipe(
165+ withLatestFrom(state$),
166+ map(([_num, state]) => state * state),
167+ ), 2)
168+ return (
169+ // 2
170+ // 4
171+ // 16
172+ // 256
173+ // ...
174+ <h1>{value}</h1>
175+ )
176+ }
177+
178+ ReactDOM.render(<App />, document.querySelector('#root'))
179+ ` ` `
180+
150181### ` useEventCallback `
151182
152183` ` ` tsx
153- declare type EventCallbackState<T, U> = [
154- ((e: SyntheticEvent<T>) => void) | typeof noop,
155- U
184+ declare type VoidAsNull<T> = T extends void ? null : T
185+
186+ declare type EventCallbackState<_T, E, U, I = void> = [
187+ (e: E) => void,
188+ [U extends void ? null : U, BehaviorSubject<U | null>, BehaviorSubject<I | null>]
156189]
157- declare type EventCallback<T, U> = (
158- eventSource$: Observable<SyntheticEvent<T>>
159- ) => Observable<U>
160-
161- declare function useEventCallback<T, U = void>(
162- callback: EventCallback<T, U>
163- ): EventCallbackState<T, U | null>
164- declare function useEventCallback<T, U = void>(
165- callback: EventCallback<T, U>,
166- initialState: U
167- ): EventCallbackState<T, U>
190+ declare type ReturnedState<T, E, U, I> = [EventCallbackState<T, E, U, I>[0], EventCallbackState<T, E, U, I>[1][0]]
191+
192+ declare type EventCallback<_T, E, U, I> = I extends void
193+ ? (eventSource$: Observable<E>, state$: Observable<U>) => Observable<U>
194+ : (eventSource$: Observable<E>, inputs$: Observable<I>, state$: Observable<U>) => Observable<U>
195+
196+ declare function useEventCallback<T, E extends SyntheticEvent<T>, U = void>(
197+ callback: EventCallback<T, E, U, void>,
198+ ): ReturnedState<T, E, U | null, void>
199+ declare function useEventCallback<T, E extends SyntheticEvent<T>, U = void>(
200+ callback: EventCallback<T, E, U, void>,
201+ initialState: U,
202+ ): ReturnedState<T, E, U, void>
203+ declare function useEventCallback<T, E extends SyntheticEvent<T>, U = void, I = void>(
204+ callback: EventCallback<T, E, U, I>,
205+ initialState: U,
206+ inputs: I,
207+ ): ReturnedState<T, E, U, I>
168208` ` `
169209
170210#### Examples :
@@ -223,3 +263,101 @@ function App() {
223263
224264ReactDOM.render(<App />, document.querySelector('#app'))
225265` ` `
266+
267+ ** With state$ :**
268+
269+ [live demo ](https :// codesandbox.io/s/m95lz934x)
270+
271+ ` ` ` tsx
272+ import React from "react";
273+ import ReactDOM from "react-dom";
274+ import { useEventCallback } from "rxjs-hooks";
275+ import { map, withLatestFrom } from "rxjs/operators";
276+
277+ function App() {
278+ const [clickCallback, [description, x, y, prevDescription]] = useEventCallback(
279+ (event$, state$) =>
280+ event$.pipe(
281+ withLatestFrom(state$),
282+ map(([event, state]) => [
283+ event.target.innerHTML,
284+ event.clientX,
285+ event.clientY,
286+ state[0],
287+ ])
288+ ),
289+ ["nothing", 0, 0, "nothing"]
290+ );
291+
292+ return (
293+ <div className="App">
294+ <h1>
295+ click position: {x}, {y}
296+ </h1>
297+ <h1>"{description}" was clicked.</h1>
298+ <h1>"{prevDescription}" was clicked previously.</h1>
299+ <button onClick={clickCallback}>click me</button>
300+ <button onClick={clickCallback}>click you</button>
301+ <button onClick={clickCallback}>click him</button>
302+ </div>
303+ );
304+ }
305+
306+ const rootElement = document.getElementById("root");
307+ ReactDOM.render(<App />, rootElement);
308+ ` ` `
309+
310+ ** A complex example : useEventCallback with both inputs$ and state$ **
311+
312+ [live demo ](https :// codesandbox.io/s/n1pn02jxym)
313+
314+ ` ` ` tsx
315+ import React, { useState } from "react";
316+ import ReactDOM from "react-dom";
317+ import { useEventCallback } from "rxjs-hooks";
318+ import { map, withLatestFrom, combineLatest } from "rxjs/operators";
319+
320+ import "./styles.css";
321+
322+ function App() {
323+ const [count, setCount] = useState(0);
324+ const [clickCallback, [description, x, y, prevDesc]] = useEventCallback(
325+ (event$, inputs$, state$) =>
326+ event$.pipe(
327+ map(event => [event.target.innerHTML, event.clientX, event.clientY]),
328+ combineLatest(inputs$),
329+ withLatestFrom(state$),
330+ map(([eventAndInput, state]) => {
331+ const [[text, x, y], [count]] = eventAndInput;
332+ const prevDescription = state[0];
333+ return [text, x + count, y + count, prevDescription];
334+ })
335+ ),
336+ ["nothing", 0, 0, "nothing"],
337+ [count]
338+ );
339+
340+ return (
341+ <div className="App">
342+ <h1>
343+ click position: {x}, {y}
344+ </h1>
345+ <h1>"{description}" was clicked.</h1>
346+ <h1>"{prevDesc}" was clicked previously.</h1>
347+ <button onClick={clickCallback}>click me</button>
348+ <button onClick={clickCallback}>click you</button>
349+ <button onClick={clickCallback}>click him</button>
350+ <div>
351+ <p>
352+ click buttons above, and then click this ` ++ + ` button, the position
353+ numbers will grow.
354+ </p>
355+ <button onClick={() => setCount(count + 1)}>+++</button>
356+ </div>
357+ </div>
358+ );
359+ }
360+
361+ const rootElement = document.getElementById("root");
362+ ReactDOM.render(<App />, rootElement);
363+ ` ` `
0 commit comments