- Notifications
You must be signed in to change notification settings - Fork85
React hooks for RxJS
NotificationsYou must be signed in to change notification settings
LeetCode-OpenSource/rxjs-hooks
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Using npm:
$ npm i --save rxjs-hooks rxjs
Or yarn:
$ yarn add rxjs-hooks rxjs
importReactfrom"react";importReactDOMfrom"react-dom/client";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/client";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>)}
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>)}
Observe props change:
importReactfrom'react'importReactDOMfrom'react-dom'import{useObservable}from'rxjs-hooks'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>)}constrootElement=document.querySelector("#app");ReactDOM.createRoot(rootElement).render(<Appfoo={1000}/>);ReactDOM.createRoot(rootElement).render(<Appfoo={2000}/>);
useObservable with state$
importReactfrom'react'importReactDOMfrom'react-dom/client'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>)}
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></>)}
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></>)}
With state$:
importReactfrom"react";importReactDOMfrom"react-dom/client";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>);}
A complex example: useEventCallback with bothinputs$
andstate$
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>);}
Example of combining callback observables coming from separate elements - animation with start/stop button and rate controllable via slider
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>);};
If you are using React 18 +StrictMode
under NODE_ENV=development,rxjs-hooks
may not work properly.facebook/react#24502 (comment)
About
React hooks for RxJS
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
No packages published
Uh oh!
There was an error while loading.Please reload this page.
Contributors15
Uh oh!
There was an error while loading.Please reload this page.