Skip to content

Instantly share code, notes, and snippets.

@nvolungis
Created June 16, 2017 17:47
Show Gist options
  • Save nvolungis/b6abdd01806c93560c267a48da9fe0f5 to your computer and use it in GitHub Desktop.
Save nvolungis/b6abdd01806c93560c267a48da9fe0f5 to your computer and use it in GitHub Desktop.
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