Subscribe event in react style
Feel tired about componentDidMount
and componentWillUnmount
pair to subscribe and unsubscribe events?
This module will help.
Feel tired about componentDidMount
and componentWillReceiveProps
and write a fetchData
method and deal with reentry issue and 'warning: setState after componentDidUnmount''?
This module will help.
Helpful for both react and react-native.
Installation
Just npm it:
npm install react-subscribe --save
API
Subscribe
Use together with fbemitter like event emitters.
Emitter should have a addListener
method, which return a subscription object.
Call remove
method of subscription object will do unsubscribe.
Now you can subscribe event like this:
;; Component state = listening = true target = someEmitter eventName = 'eventName' { }; { return <div> /* This will render nothing: */ <Subscribe target=someEmitter eventName="eventName" listener=thisonEvent /> /* You can subscribe many event here. */ <Subscribe target=someEmitter eventName="otherEvent" listener=thisonEvent /> /* You can subscribe with a condition. */ /* It will subscribe/unsubscribe when condition changes and this component re-renders. */ thisstatelistening && <Subscribe target=someEmitter eventName="eventName" listener=thisonEvent /> /* You can use expression for target & eventName and change it after re-render.*/ /* This will safely unsubscribe old target/eventName and resubscribe the new one(s).*/ <Subscribe target=thisstatetarget eventName=thisstateeventName listener=thisonEvent /> </div> ; }
Subscribe will automatic begin when after component mount and automatic unsubscribe before component unmount.
In the case when your component renders a component that should not have any children or have special meaning with children (like TabBar from react-native), you should use Subscribe in this form:
Component { }; { // This component will render only a <input /> return <Subscribe target=someEmitter eventName="eventName" listener=thisonEvent> <input /> </Subscribe> ; }
If you use react 16+, you also can use React.Fragment instead:
Component { }; { // This component will render only a <input /> return <ReactFragment> <input /> <Subscribe target=someEmitter eventName="eventName" listener=thisonEvent /> </ReactFragment> ; }
SubscribeDOM
Use SubscribeDOM
instead of Subscribe when subscribing a DOM Event.
Component { // Move indicates when document scrolls. const val = documentbodyscrollTop / documentbodyoffsetHeight; thisrefsactivestyletop = val * 20 + 'px'; }; return return <div> /* Other body components */ <SubscribeDOM target=document eventName="scroll" listener=thisonBodyWheel /> <div ref="active" className= /> </div> ;
Timer
Use Timer
instead of setInterval
and clearInterval
.
; Component state = cd: 60 ; { this; }; return if thisstatecd <= 0 return <div>Cooldown is over and onTimer will not be called again!</div>; return <div> <Timer interval=1000 onTimer=thisonTimer /> There is still thisstatecd seconds to go </div> ;
Note: If you change interval value, the timer will be reset.
eg: You have a timer which interval is 60 seconds, and you click a button after 30 second which changes interval into 40 seconds, The next event will be fired 40 seconds later (totally 70 seconds after your component mounted) which may let user feel weired.
Fetch
Use Fetch
instead of fetch
or promise. Fetch will auto reload when url
or type
changes.
{ if loading return <div>loading...</div>; if error return <div> Error: errormessage' ' <a href="#" onClick=reload> Reload </a> </div> ; return <div> <p>Status Code: statusCode</p> <p>JSON</p> </div> ;} const FETCH_OPTION = method: 'POST' headers: 'X-AccessToken': 'some_token' credentials: 'include' // Default credentials is 'same-origin' in `Fetch`; { const id = props; return <div> <Fetch url=`/some/api/` type="json" option=FETCH_OPTION> <SomeComponent /> </Fetch> </div> ;}
Use function as children if you don't want to seperate component:
{ const id = props; return <div> <Fetch url=`/some/api/` type="json" option=FETCH_OPTION> { return <div>data && <p>JSON</p></div>; } </Fetch> </div> ;}
Use 'doFetch' props to provide a custom async function.
{ return 'Hello, world!';} { return <div> <Fetch doFetch=customRequest url="foo"> <SomeComponent /> </Fetch> </div> ;}
Maybe you want use Axios instead of fetch, I suggest you to use axios status/error management:
{ if loading return <div>loading...</div>; if error return <div> <p>Error: errormessage </p> <p>StatusCode: errorresponsestatus</p> <p>JSON</p> <a href="#" onClick=reload> Reload </a> </div> ; return <div> <p>Status Code: datastatus</p> <p>JSON</p> </div> ;} Component { <div> <Fetch doFetch=Axiosget url="foo"> <SomeComponent /> </Fetch> </div>; }