import * as React from "react";
import { createSubscription, Subscription } from "create-subscription";
//
// Example: Subscribing to event dispatchers
// https://github.com/facebook/react/blob/fa7fa812c70084e139d13437fb204fcdf9152299/packages/create-subscription/README.md#subscribing-to-event-dispatchers
// ----------------------------------------------------------------------------
// Start with a simple component.
// In this case, it's a functional component, but it could have been a class.
function FollowerComponent({ followersCount }: { followersCount: number }) {
return
You have {followersCount} followers!
;
}
interface EventDispatcher {
value: T;
addEventListener(eventName: "change", onChange: (newValue: T) => any): void;
removeEventListener(eventName: "change", onChange: (newValue: T) => any): void;
}
// Create a wrapper component to manage the subscription.
// $ExpectType Subscription, number>
const EventHandlerSubscription = createSubscription({
getCurrentValue: (eventDispatcher: EventDispatcher) => eventDispatcher.value,
subscribe: (eventDispatcher: EventDispatcher, callback) => {
const onChange = (event: any) => callback(eventDispatcher.value);
eventDispatcher.addEventListener("change", onChange);
return () => eventDispatcher.removeEventListener("change", onChange);
}
});
declare const eventDispatcher: EventDispatcher;
// Your component can now be used as shown below.
// In this example, 'eventDispatcher' represents a generic event dispatcher.
{value => {
// $ExpectType number
const followersCount = value;
return ;
}}
;
//
// Example: Subscribing to event dispatchers
// https://github.com/facebook/react/blob/fa7fa812c70084e139d13437fb204fcdf9152299/packages/create-subscription/README.md#subscribing-to-a-promise
// ----------------------------------------------------------------------------
// Start with a simple component.
const LoadingComponent: React.SFC<{ loadingStatus: string | undefined }> = ({ loadingStatus }) => {
if (loadingStatus === undefined) {
// Loading
} else if (loadingStatus === null) {
// Error
} else {
// Success
}
return null;
};
// Wrap the functional component with a subscriber HOC.
// This HOC will manage subscriptions and pass values to the decorated component.
// It will add and remove subscriptions in an async-safe way when props change.
// $ExpectType Subscription, string | undefined>
const PromiseSubscription = createSubscription({
getCurrentValue: promise => {
// There is no way to synchronously read a Promise's value,
// So this method should return undefined.
return undefined;
},
subscribe: (promise: Promise, callback: (newValue: string | undefined) => void) => {
promise.then(
// Success
callback,
// Failure
() => callback(undefined)
);
// There is no way to "unsubscribe" from a Promise.
// create-subscription will still prevent stale values from rendering.
return () => {};
}
});
declare const loadingPromise: Promise;
// Your component can now be used as shown below.
{value => {
// $ExpectType string | undefined
const loadingStatus = value;
return ;
}}
;
//
// Error cases
// ----------------------------------------------------------------------------
declare const wrongPromise: Promise;
// $ExpectError
{value => null}
;
// $ExpectError
const MismatchSubscription = createSubscription({ getCurrentValue: (a: number) => null, subscribe: (a: string, callback) => (() => undefined) });
// $ExpectError
const NoUnsubscribe = createSubscription({ getCurrentValue: (a: number) => a, subscribe: (a: number, callback) => { /* oops, should've returned a callback here */ }});