Skip to content

Instantly share code, notes, and snippets.

@tonyonodi
Last active March 21, 2019 19:35
Show Gist options
  • Save tonyonodi/675d14f8e7e3218d32511ee585a27fa0 to your computer and use it in GitHub Desktop.
Save tonyonodi/675d14f8e7e3218d32511ee585a27fa0 to your computer and use it in GitHub Desktop.
import * as React from "react";
import { interval, Observable, fromEvent, merge } from "rxjs";
import { map, scan, mapTo } from "rxjs/operators";
const { useState, useEffect, useRef } = React;
function useStream<T>(streamContainer: () => Observable<T>, initialValue: T) {
const [state, setState] = useState(initialValue);
useEffect(() => {
const stream = streamContainer();
stream.subscribe((val: any) => {
setState(val);
});
}, []);
return state;
}
const myStreamContainer = (button: React.RefObject<HTMLButtonElement>) => () => {
const timer = interval(1000).pipe(
map(t => {
return { time: t };
})
);
const clickStream = fromEvent(
button.current as HTMLButtonElement,
"click"
).pipe(
mapTo(1),
scan((acc, one) => acc + one, 0),
map(cCount => ({ clickCount: cCount }))
);
return merge(timer, clickStream).pipe(
scan((prevState, evt) => ({ ...prevState, ...evt }), {
time: 0,
clickCount: 0,
})
);
};
function App() {
const button = useRef<HTMLButtonElement>(null);
const { time, clickCount } = useStream(myStreamContainer(button), {
time: 0,
clickCount: 0,
});
return (
<div>
<button ref={button}>Click me</button>
<p>
You have clicked the button {clickCount} times in {time} seconds.
</p>
</div>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment