main
md 108 lines 3.46 KB
Rendered Raw
1 # use-subscription
2
3 React Hook for subscribing to external data sources.
4
5 **You may now migrate to [`use-sync-external-store`](https://www.npmjs.com/package/use-sync-external-store) directly instead, which has the same API as [`React.useSyncExternalStore`](https://react.dev/reference/react/useSyncExternalStore). The `use-subscription` package is now a thin wrapper over `use-sync-external-store` and will not be updated further.**
6
7 # Installation
8
9 ```sh
10 # Yarn
11 yarn add use-subscription
12
13 # NPM
14 npm install use-subscription
15 ```
16
17 # Usage
18
19 To configure a subscription, you must provide two methods: `getCurrentValue` and `subscribe`.
20
21 In order to avoid removing and re-adding subscriptions each time this hook is called, the parameters passed to this hook should be memoized. This can be done by wrapping the entire subscription with `useMemo()`, or by wrapping the individual callbacks with `useCallback()`.
22
23 ## Subscribing to event dispatchers
24
25 Below is an example showing how `use-subscription` can be used to subscribe to event dispatchers such as DOM elements.
26
27 ```js
28 import React, { useMemo } from "react";
29 import { useSubscription } from "use-subscription";
30
31 // In this example, "input" is an event dispatcher (e.g. an HTMLInputElement)
32 // but it could be anything that emits an event and has a readable current value.
33 function Example({ input }) {
34
35 // Memoize to avoid removing and re-adding subscriptions each time this hook is called.
36 const subscription = useMemo(
37 () => ({
38 getCurrentValue: () => input.value,
39 subscribe: callback => {
40 input.addEventListener("change", callback);
41 return () => input.removeEventListener("change", callback);
42 }
43 }),
44
45 // Re-subscribe any time our input changes
46 // (e.g. we get a new HTMLInputElement prop to subscribe to)
47 [input]
48 );
49
50 // The value returned by this hook reflects the input's current value.
51 // Our component will automatically be re-rendered when that value changes.
52 const value = useSubscription(subscription);
53
54 // Your rendered output goes here ...
55 }
56 ```
57
58 ## Subscribing to observables
59
60 Below are examples showing how `use-subscription` can be used to subscribe to certain types of observables (e.g. RxJS `BehaviorSubject` and `ReplaySubject`).
61
62 **Note** that it is not possible to support all observable types (e.g. RxJS `Subject` or `Observable`) because some provide no way to read the "current" value after it has been emitted.
63
64 ### `BehaviorSubject`
65 ```js
66 const subscription = useMemo(
67 () => ({
68 getCurrentValue: () => behaviorSubject.getValue(),
69 subscribe: callback => {
70 const subscription = behaviorSubject.subscribe(callback);
71 return () => subscription.unsubscribe();
72 }
73 }),
74
75 // Re-subscribe any time the behaviorSubject changes
76 [behaviorSubject]
77 );
78
79 const value = useSubscription(subscription);
80 ```
81
82 ### `ReplaySubject`
83 ```js
84 const subscription = useMemo(
85 () => ({
86 getCurrentValue: () => {
87 let currentValue;
88 // ReplaySubject does not have a sync data getter,
89 // So we need to temporarily subscribe to retrieve the most recent value.
90 replaySubject
91 .subscribe(value => {
92 currentValue = value;
93 })
94 .unsubscribe();
95 return currentValue;
96 },
97 subscribe: callback => {
98 const subscription = replaySubject.subscribe(callback);
99 return () => subscription.unsubscribe();
100 }
101 }),
102
103 // Re-subscribe any time the replaySubject changes
104 [replaySubject]
105 );
106
107 const value = useSubscription(subscription);
108 ```