create-subscription
create-subscription
is a utility for subscribing to external data sources inside React components.
It is no longer maintained and will not be updated. Use the built-in React.useSyncExternalStore
instead.
Installation
yarn add create-subscription
npm install create-subscription
Usage
To configure a subscription, you must provide two methods: getCurrentValue
and subscribe
.
import { createSubscription } from "create-subscription";
const Subscription = createSubscription({
getCurrentValue(source) {
},
subscribe(source, callback) {
}
});
To use the Subscription
component, pass the subscribable property (e.g. an event dispatcher, observable) as the source
property and use a render prop, children
, to handle the subscribed value when it changes:
<Subscription source={eventDispatcher}>
{value => <AnotherComponent value={value} />}
</Subscription>
Examples
This API can be used to subscribe to a variety of "subscribable" sources, from event dispatchers to RxJS observables. Below are a few examples of how to subscribe to common types.
Subscribing to event dispatchers
Below is an example showing how create-subscription
can be used to subscribe to event dispatchers such as DOM elements.
import React from "react";
import { createSubscription } from "create-subscription";
function FollowerComponent({ followersCount }) {
return <div>You have {followersCount} followers!</div>;
}
const EventHandlerSubscription = createSubscription({
getCurrentValue: eventDispatcher => eventDispatcher.value,
subscribe: (eventDispatcher, callback) => {
const onChange = event => callback(eventDispatcher.value);
eventDispatcher.addEventListener("change", onChange);
return () => eventDispatcher.removeEventListener("change", onChange);
}
});
<EventHandlerSubscription source={eventDispatcher}>
{value => <FollowerComponent followersCount={value} />}
</EventHandlerSubscription>;
Subscribing to observables
Below are examples showing how create-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.
BehaviorSubject
const BehaviorSubscription = createSubscription({
getCurrentValue: behaviorSubject => behaviorSubject.getValue(),
subscribe: (behaviorSubject, callback) => {
const subscription = behaviorSubject.subscribe(callback);
return () => subscription.unsubscribe();
}
});
ReplaySubject
const ReplaySubscription = createSubscription({
getCurrentValue: replaySubject => {
let currentValue;
replaySubject
.subscribe(value => {
currentValue = value;
})
.unsubscribe();
return currentValue;
},
subscribe: (replaySubject, callback) => {
const subscription = replaySubject.subscribe(callback);
return () => subscription.unsubscribe();
}
});
Subscribing to a Promise
Below is an example showing how create-subscription
can be used with native Promises.
Note that an initial render value of undefined
is unavoidable due to the fact that Promises provide no way to synchronously read their current value.
Note the lack of a way to "unsubscribe" from a Promise can result in memory leaks as long as something has a reference to the Promise. This should be taken into consideration when determining whether Promises are appropriate to use in this way within your application.
import React from "react";
import { createSubscription } from "create-subscription";
function LoadingComponent({ loadingStatus }) {
if (loadingStatus === undefined) {
} else if (loadingStatus === null) {
} else {
}
}
const PromiseSubscription = createSubscription({
getCurrentValue: promise => {
return undefined;
},
subscribe: (promise, callback) => {
promise.then(
value => callback(value),
() => callback(null)
);
return () => {};
}
});
<PromiseSubscription source={loadingPromise}>
{loadingStatus => <LoadingComponent loadingStatus={loadingStatus} />}
</PromiseSubscription>