


Using npm:
$ npm i --save rxjs-hooks
Or yarn:
importReactfrom"react";importReactDOMfrom"react-dom";import{useObservable}from"rxjs-hooks";import{interval}from"rxjs";import{map}from"rxjs/operators";functionApp(){constvalue=useObservable(()=>interval(500).pipe(map((val)=>val*3)));return(<divclassName="App"><h1>Incremental number:{value}</h1></div>);}
importReactfrom"react";importReactDOMfrom"react-dom";import{useEventCallback}from"rxjs-hooks";import{map}from"rxjs/operators";functionApp(){const[clickCallback,[description,x,y]]=useEventCallback((event$)=>event$.pipe(map((event)=>[event.target.innerHTML,event.clientX,event.clientY]),),["nothing",0,0],)return(<divclassName="App"><h1>click position:{x},{y}</h1><h1>"{description}" was clicked.</h1><buttononClick={clickCallback}>click me</button><buttononClick={clickCallback}>click you</button><buttononClick={clickCallback}>click him</button></div>);}
exporttypeInputFactory<State>=(state$:Observable<State>)=>Observable<State>exporttypeInputFactoryWithInputs<State,Inputs>=(state$:Observable<State>,inputs$:Observable<RestrictArray<Inputs>>,)=>Observable<State>exportfunctionuseObservable<State>(inputFactory:InputFactory<State>):State|nullexportfunctionuseObservable<State>(inputFactory:InputFactory<State>,initialState:State):StateexportfunctionuseObservable<State,Inputs>(inputFactory:InputFactoryWithInputs<State,Inputs>,initialState:State,inputs:RestrictArray<Inputs>,):State
importReactfrom'react'importReactDOMfrom'react-dom'import{useObservable}from'rxjs-hooks'import{of}from'rxjs'functionApp(){constvalue=useObservable(()=>of(1000))return(// render twice// null and 1000<h1>{value}</h1>)}ReactDOM.render(<App/>,document.querySelector('#app'))
With default value:
importReactfrom'react'importReactDOMfrom'react-dom'import{useObservable}from'rxjs-hooks'import{of}from'rxjs'functionApp(){constvalue=useObservable(()=>of(1000),200)return(// render twice// 200 and 1000<h1>{value}</h1>)}ReactDOM.render(<App/>,document.querySelector('#app'))
Observe props change:
importReactfrom'react'importReactDOMfrom'react-dom'import{useObservable}from'rxjs-hooks'import{of}from'rxjs'import{map}from'rxjs/operators'functionApp(props:{foo:number}){constvalue=useObservable((_,inputs$)=>inputs$.pipe(map(([val])=>val+1),),200,[props.foo])return(// render three times// 200 and 1001 and 2001<h1>{value}</h1>)}ReactDOM.render(<Appfoo={1000}/>,document.querySelector('#app'))ReactDOM.render(<Appfoo={2000}/>,document.querySelector('#app'))
useObservable with state$
live demo
importReactfrom'react'importReactDOMfrom'react-dom'import{useObservable}from'rxjs-hooks'import{interval}from'rxjs'import{map,withLatestFrom}from'rxjs/operators'functionApp(){constvalue=useObservable((state$)=>interval(1000).pipe(withLatestFrom(state$),map(([_num,state])=>state*state),),2)return(// 2// 4// 16// 256// ...<h1>{value}</h1>)}ReactDOM.render(<App/>,document.querySelector('#root'))
importReactfrom'react'importReactDOMfrom'react-dom'import{useEventCallback}from'rxjs-hooks'import{mapTo}from'rxjs/operators'functionApp(){const[clickCallback,value]=useEventCallback((event$:Observable<React.SyntheticEvent<HTMLButtonElement>>)=>event$.pipe(mapTo(1000)))return(// render null// click button// render 1000<><h1>{value}</h1><buttononClick={clickCallback}>click me</button></>)}ReactDOM.render(<App/>,document.querySelector('#app'))
With initial value:
importReactfrom'react'importReactDOMfrom'react-dom'import{useEventCallback}from'rxjs-hooks'import{mapTo}from'rxjs/operators'functionApp(){const[clickCallback,value]=useEventCallback((event$:Observable<React.SyntheticEvent<HTMLButtonElement>>)=>event$.pipe(mapTo(1000)),200,)return(// render 200// click button// render 1000<><h1>{value}</h1><buttononClick={clickCallback}>click me</button></>)}ReactDOM.render(<App/>,document.querySelector('#app'))
With state$:
live demo
importReactfrom"react";importReactDOMfrom"react-dom";import{useEventCallback}from"rxjs-hooks";import{map,withLatestFrom}from"rxjs/operators";functionApp(){const[clickCallback,[description,x,y,prevDescription]]=useEventCallback((event$,state$)=>event$.pipe(withLatestFrom(state$),map(([event,state])=>[event.target.innerHTML,event.clientX,event.clientY,state[0],])),["nothing",0,0,"nothing"]);return(<divclassName="App"><h1> click position:{x},{y}</h1><h1>"{description}" was clicked.</h1><h1>"{prevDescription}" was clicked previously.</h1><buttononClick={clickCallback}>click me</button><buttononClick={clickCallback}>click you</button><buttononClick={clickCallback}>click him</button></div>);}constrootElement=document.getElementById("root");ReactDOM.render(<App/>,rootElement);
A complex example: useEventCallback with both inputs$ and state$
live demo
importReact,{useState}from"react";importReactDOMfrom"react-dom";import{useEventCallback}from"rxjs-hooks";import{map,withLatestFrom,combineLatest}from"rxjs/operators";import"./styles.css";functionApp(){const[count,setCount]=useState(0);const[clickCallback,[description,x,y,prevDesc]]=useEventCallback((event$,state$,inputs$)=>event$.pipe(map(event=>[event.target.innerHTML,event.clientX,event.clientY]),combineLatest(inputs$),withLatestFrom(state$),map(([eventAndInput,state])=>{const[[text,x,y],[count]]=eventAndInput;constprevDescription=state[0];return[text,x+count,y+count,prevDescription];})),["nothing",0,0,"nothing"],[count]);return(<divclassName="App"><h1> click position:{x},{y}</h1><h1>"{description}" was clicked.</h1><h1>"{prevDesc}" was clicked previously.</h1><buttononClick={clickCallback}>click me</button><buttononClick={clickCallback}>click you</button><buttononClick={clickCallback}>click him</button><div><p> click buttons above, and then click this `+++` button, the position numbers will grow.</p><buttononClick={()=>setCount(count+1)}>+++</button></div></div>);}constrootElement=document.getElementById("root");ReactDOM.render(<App/>,rootElement);
Example of combining callback observables coming from separate elements - animation with start/stop button and rate controllable via slider
live demo
constAnimation=({ frame})=>{constframes="|/-\\|/-\\|".split("");return(<div><p>{frames[frame%frames.length]}</p></div>);};constApp=()=>{constdefaultRate=5;const[running,setRunning]=useState(false);const[onEvent,frame]=useEventCallback(events$=>{construnning$=events$.pipe(filter(e=>e.type==="click"),scan(running=>!running,running),startWith(running),tap(setRunning));returnevents$.pipe(filter(e=>e.type==="change"),map(e=>parseInt(e.target.value,10)),startWith(defaultRate),switchMap(i=>timer(200,1000/i)),withLatestFrom(running$),filter(([_,running])=>running),scan(frame=>frame+1,0));});return(<divclassName="App"><buttononClick={onEvent}>{running ?"Stop" :"Start"}</button><inputtype="range"onChange={onEvent}defaultValue={defaultRate}min="1"max="10"></input><Animationframe={frame}/></div>);};