Skip to content

Instantly share code, notes, and snippets.

@arleighdickerson
Created July 9, 2023 17:22
Show Gist options
  • Save arleighdickerson/250bbc88b829af41a84eb7a4f8d5d3ca to your computer and use it in GitHub Desktop.
Save arleighdickerson/250bbc88b829af41a84eb7a4f8d5d3ca to your computer and use it in GitHub Desktop.
PromiseGate
import { Component, ReactNode } from 'react';
interface Props {
loading: ReactNode;
ready: PromiseLike<any>;
beforeMount?: () => any;
afterLift?: () => any;
}
interface State {
bootstrapped: boolean;
subscribed: boolean;
}
export default class PromiseGate extends Component<Props, State> {
static readonly defaultProps = {
loading: null,
afterLift: () => {},
beforeMount: () => {},
} as const;
private rendered: boolean = false;
constructor(props: Props, context?: any) {
super(props, context);
this.state = {
bootstrapped: false,
subscribed: true,
};
}
componentWillMount() {
this.props.beforeMount!();
}
componentDidMount() {
if (!this.state.bootstrapped) {
this.props.ready.then(() => {
if (this.state.subscribed) {
this.setState({ bootstrapped: true, subscribed: false });
}
});
}
}
componentDidUpdate(prevProps: Props, prevState: State) {
if (!prevState.bootstrapped && this.state.bootstrapped) {
this.props.afterLift!();
}
}
componentWillUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any) {
if (nextState.bootstrapped) {
this.rendered = true;
}
}
shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any): boolean {
return !this.rendered && nextState.bootstrapped;
}
componentWillUnmount() {
this.setState({ subscribed: false });
}
render() {
return <>{this.state.bootstrapped ? this.props.children : this.props.loading}</>;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment