React Hook for subscribing to external data sources.
You may now migrate to use-sync-external-store
directly instead, which has the same API as React.useSyncExternalStore
. The use-subscription
package is now a thin wrapper over use-sync-external-store
and will not be updated further.
# Yarn yarn add use-subscription # NPM npm install use-subscription
To configure a subscription, you must provide two methods: getCurrentValue
and subscribe
.
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()
.
Below is an example showing how use-subscription
can be used to subscribe to event dispatchers such as DOM elements.
importReact,{useMemo}from"react";import{useSubscription}from"use-subscription";// In this example, "input" is an event dispatcher (e.g. an HTMLInputElement)// but it could be anything that emits an event and has a readable current value.functionExample({ input }){// Memoize to avoid removing and re-adding subscriptions each time this hook is called.constsubscription=useMemo(()=>({getCurrentValue: ()=>input.value,subscribe: callback=>{input.addEventListener("change",callback);return()=>input.removeEventListener("change",callback);}}),// Re-subscribe any time our input changes// (e.g. we get a new HTMLInputElement prop to subscribe to)[input]);// The value returned by this hook reflects the input's current value.// Our component will automatically be re-rendered when that value changes.constvalue=useSubscription(subscription);// Your rendered output goes here ...}
Below are examples showing how use-subscription
can be used to subscribe to certain types of observables (e.g. RxJS BehaviorSubject
and ReplaySubject
).
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.
constsubscription=useMemo(()=>({getCurrentValue: ()=>behaviorSubject.getValue(),subscribe: callback=>{constsubscription=behaviorSubject.subscribe(callback);return()=>subscription.unsubscribe();}}),// Re-subscribe any time the behaviorSubject changes[behaviorSubject]);constvalue=useSubscription(subscription);
constsubscription=useMemo(()=>({getCurrentValue: ()=>{letcurrentValue;// ReplaySubject does not have a sync data getter,// So we need to temporarily subscribe to retrieve the most recent value.replaySubject.subscribe(value=>{currentValue=value;}).unsubscribe();returncurrentValue;},subscribe: callback=>{constsubscription=replaySubject.subscribe(callback);return()=>subscription.unsubscribe();}}),// Re-subscribe any time the replaySubject changes[replaySubject]);constvalue=useSubscription(subscription);