Skip to content

Instantly share code, notes, and snippets.

@pmunin
Last active March 21, 2018 22:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pmunin/6872f2cd856936cb1dea50b4c8402b79 to your computer and use it in GitHub Desktop.
Save pmunin/6872f2cd856936cb1dea50b4c8402b79 to your computer and use it in GitHub Desktop.
React Component allows to subscribe to events on mounting and unsubscribe those events on unmounting
import React from 'react'
export class Subscribe extends React.Component
{
state={
//subscriptions:[],
childrenParams:[]
}
render(){
var subscribeToItems = this.props.to instanceof Array?this.props.to : [this.props.to]
return <React.Fragment>
{subscribeToItems.map((subscribeToFunc,index)=>{
return <SubscribeSingle
key={index}
to={subscribeToFunc}
ref={this.setRefs[index]=this.setRefs[index]||(ref=>{
this.subscriptions[index] = ref;
})}
onStateChanged={this.onStateChanged[index]=this.onStateChanged[index]||(newState=>{
let childrenParams = [...this.state.childrenParams];
childrenParams[index] = newState;
this.setState({childrenParams: childrenParams})
})}
/>
})}
{
(typeof this.props.children==="function")? this.props.children(...this.state.childrenParams):this.props.children||null
}
</React.Fragment>
}
setRefs=[]
onStateChanged=[]
subscriptions=[]
}
class SubscribeSingle extends React.Component
{
state={
subscription:null,
}
render()
{
if(this.props.children instanceof Function)
return this.props.children(this.state, this)
else
return this.props.children || null
}
componentDidMount()
{
this.subscribe(this.props)
}
componentWillUnmount()
{
this.unsubscribe();
}
componentWillReceiveProps(props)
{
//this.subscribe(props)
}
subscribe(props)
{
this.unsubscribe()
let subscribeFunc = this.props.to;
if(!subscribeFunc) return;
let unsubscribeFunc = subscribeFunc((newState)=>{
this.setState(newState, ()=>{
if(this.props.onStateChanged)
this.props.onStateChanged(this.state, this);
})
});
this.setState({subscription:{
unsubscribe:unsubscribeFunc
}})
}
unsubscribe()
{
const subscription = this.state.subscription;
if(subscription&&subscription.unsubscribe) subscription.unsubscribe();
this.setState({subscription:null});
}
}
export class Example extends React.Component
{
cache=[]
state={
mounted:false
}
render()
{
let mousemoveEvent = this.state.mousemoveEvent; //mousemoveState&&mousemoveState.lastEvent;
let mousedownEvent = this.state.mousedownEvent; //mousedownState&&mousedownState.lastEvent;
return <div>
<button onClick={()=>{
this.setState({mounted:!this.state.mounted});
}}>Mount/Unmount</button>
{this.state.mounted?
<div>
<Subscribe to={//this.cache[0]=this.cache[0]||
([
(setState)=>{
let handler;
console.log("Subscribe mousemove");
window.addEventListener("mousemove",handler=e=>{
//can use this.setState({mousemove:e}) instead
//setState({lastEvent:e});
this.setState({mousemoveEvent:e})
})
return ()=>{
console.log("Unsubscribe mousemove");
window.removeEventListener("mousemove",handler);
}
},
(setState)=>{
let handler;
console.log("Subscribe mousedown");
window.addEventListener("mousedown",handler=e=>{
//can use this.setState({mousedown:e}) instead
//setState({lastEvent:e});
this.setState({mousedownEvent:e})
})
return ()=>{
console.log("Unsubscribe mousedown");
window.removeEventListener("mousedown",handler);
}
},
]
)}>
{/* can also render as a children function, taking subscriptions states:
{
(mousemoveState, mousedownState)=>{
let mousemoveEvent = this.state.mousemoveEvent; //mousemoveState&&mousemoveState.lastEvent;
let mousedownEvent = this.state.mousedownEvent; //mousedownState&&mousedownState.lastEvent;
return <div>
Mouse move: x:{mousemoveEvent&&mousemoveEvent.clientX} y:{mousemoveEvent&&mousemoveEvent.clientY}<br/>
Mouse down: x:{mousedownEvent&&mousedownEvent.clientX} y:{mousedownEvent&&mousedownEvent.clientY}<br/>
</div>
}
} */}
</Subscribe>
<div>
Mouse move: x:{mousemoveEvent&&mousemoveEvent.clientX} y:{mousemoveEvent&&mousemoveEvent.clientY}<br/>
Mouse down: x:{mousedownEvent&&mousedownEvent.clientX} y:{mousedownEvent&&mousedownEvent.clientY}<br/>
</div>
</div>:"Unmounted"
}
</div>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment