@@ -77,11 +77,13 @@ function App() {
77
77
### ` useObservable `
78
78
79
79
``` 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 >
81
83
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
85
87
```
86
88
87
89
#### Examples :
@@ -147,24 +149,62 @@ ReactDOM.render(<App foo={1000} />, document.querySelector('#app'))
147
149
ReactDOM.render(<App foo={2000} />, document.querySelector('#app'))
148
150
` ` `
149
151
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
+
150
181
### ` useEventCallback `
151
182
152
183
` ` ` 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>]
156
189
]
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>
168
208
` ` `
169
209
170
210
#### Examples :
@@ -223,3 +263,101 @@ function App() {
223
263
224
264
ReactDOM.render(<App />, document.querySelector('#app'))
225
265
` ` `
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