Skip to content

Instantly share code, notes, and snippets.

@derek-duncan
Created April 18, 2017 13:38
Show Gist options
  • Save derek-duncan/a71a8c3f6bade9a4a5c988acb13d7c06 to your computer and use it in GitHub Desktop.
Save derek-duncan/a71a8c3f6bade9a4a5c988acb13d7c06 to your computer and use it in GitHub Desktop.
Assists react in mounting/unmounting large component trees. Originally inspired by mobile twitter.
import React, { Component } from 'react';
const withDeferRender = Presentational =>
class DeferRender extends Component {
state = {
shouldRender: false,
};
componentDidMount() {
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() =>
this.setState(() => ({ shouldRender: true })));
});
}
render() {
if (!this.state.shouldRender) return null;
return <Presentational {...this.props} />;
}
};
export default withDeferRender;
@jsvg
Copy link

jsvg commented Aug 9, 2017

This is great, however if the component unmounts between animation frames, setState will throw for firing against a removed component. Ensures extra safety against a component unmounting quickly in a transition for example.

  componentDidMount() {
    this.raf = window.requestAnimationFrame(() => {
      this.recursiveRaf = window.requestAnimationFrame(() => this.setState({ mounting: false }));
    });
  }

  componentWillUnmount() {
    window.cancelAnimationFrame(this.raf);
    window.cancelAnimationFrame(this.recursiveRaf);
  }

@merraysy
Copy link

@jsvg Good catch, but I think storing both the rAF tokens is an overkill because the requests would never coexist, here is how it should be :

componentDidMount() {
  this.raf = window.requestAnimationFrame(() => {
    // at this point the first request has been fulfilled
    // let's reuse the same class property to store the second token
    this.raf = window.requestAnimationFrame(() => this.setState({ mounting: false }));
  });
}

componentWillUnmount() {
  window.cancelAnimationFrame(this.raf);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment