Last active
March 21, 2018 22:19
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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