Created
June 16, 2017 17:47
-
-
Save nvolungis/b6abdd01806c93560c267a48da9fe0f5 to your computer and use it in GitHub Desktop.
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 const RAFHOC = Component => class RAF extends React.Component { | |
constructor() { | |
super(); | |
this.state = { isRunning: false }; | |
} | |
componentWillUpdate(nextProps, nextState) { | |
if (nextState.isRunning === this.state.isRunning) return; | |
if (nextState.isRunning === true) { | |
this.nextFrame(); | |
} else { | |
this.cancelFrame(); | |
} | |
} | |
componentWillUnmount() { | |
this.stopLoop(); | |
} | |
nextFrame () { | |
// Keep a reference to the animation request to be able to clear it on | |
// stopAnimationLoop() | |
this.animationRequestId = window.requestAnimationFrame(this.animationCb); | |
} | |
cancelFrame () { | |
if (this.animationRequestId) { | |
window.cancelAnimationFrame(this._animationRequestId); | |
this.animationRequestId = null; | |
} | |
} | |
animationCb = () => { | |
if (typeof this.frameCb != 'function') return | |
this.frameCb(); | |
// Sometimes the next frame is still called even after it was canceled, so | |
// we need to make sure we don't continue with the animation loop | |
if (this.animationRequestId) { | |
this.nextFrame(); | |
} | |
}; | |
setFrameCallback = cb => { | |
this.frameCb = cb; | |
}; | |
startLoop = () => { | |
this.setState({ isRunning: true }); | |
this.animationCb(); | |
}; | |
stopLoop = () => { | |
this.setState({ isRunning: false }); | |
}; | |
render() { | |
// Pass props into wrapped component that all the child to start, | |
// stop, and set the callback function ( to be called on each frame) | |
return <Component | |
startLoop={ this.startLoop } | |
stopLoop={ this.stopLoop } | |
setFrameCallback={ this.setFrameCallback } | |
/> | |
} | |
}; | |
// The RAFHOC will inject | |
// | |
// setFrameCallback | |
// startLoop | |
// stopLoop | |
class Test extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { loops: 0 }; | |
props.setFrameCallback(this.onLoop); | |
} | |
componentDidMount() { | |
this.props.startLoop(); | |
setTimeout(() => { | |
this.props.stopLoop(); | |
}, 2000); | |
} | |
onLoop() { | |
console.log('onLoop'); | |
} | |
render() { | |
return ( | |
<div>{ this.state.loops }</div> | |
) | |
} | |
} | |
export default RAFHOC(Test); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment