Skip to content

Instantly share code, notes, and snippets.

@InfiniteXyy
Created January 24, 2021 13:07
Show Gist options
  • Save InfiniteXyy/16cd24a478327a425fdf1777826d5b40 to your computer and use it in GitHub Desktop.
Save InfiniteXyy/16cd24a478327a425fdf1777826d5b40 to your computer and use it in GitHub Desktop.
subscribe everything with "$"
import React, { useCallback, useEffect, useRef, useState } from "react";
import { timer } from "rxjs";
import { take, map } from "rxjs/operators";
type Subscription = { unsubscribe: () => void }
type Observable<T> = { subscribe: (next: (value: T) => void) => Subscription }
const useSubscriber = () => {
const [, forceRefresh] = useState({});
const subscriptionsRef = useRef(new Map<Observable<any>, Subscription>());
const statesRef = useRef(new Map<Observable<any>, any>());
useEffect(() => () => {
for (const subscription of subscriptionsRef.current.values()) {
subscription.unsubscribe();
}
}, []);
const $: <T extends any>(observable: Observable<T>) => T = useCallback((subject) => {
const subscriptions = subscriptionsRef.current;
const states = statesRef.current;
if (!subscriptions.has(subject)) {
subscriptions.set(subject, subject.subscribe((value) => {
states.set(subject, value);
forceRefresh({});
}));
}
return states.get(subject);
}, []);
return $;
};
const count = timer(0, 250).pipe(
map((_, index) => index),
take(40)
);
function App() {
const $ = useSubscriber();
return (
<div>
<h1>{$(count)}</h1>
</div>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment