SafePureComponent
import * as React from 'react'; | |
import * as Models from './models'; | |
export class SafePureComponent<P, S extends Models.SafePureComponentState> extends React.PureComponent<P, S> { | |
private hasError: boolean = false; | |
constructor(props: P, context?: any) { | |
super(props, context); | |
} | |
public componentDidMount() { | |
this.setState({ hasError: this.hasError }); | |
} | |
public render() { | |
// componentDidCatch doesn't work in React 16's renderToString | |
// https://github.com/facebook/react/issues/10442 | |
// Due to streaming nature of renderToString in React 16, need to wrap each render method in try/catch | |
try { | |
// Using error boundaries for client-side rendering | |
if (this.state && this.state.hasError) { | |
return this.renderErrorView(); | |
} | |
return this.safeRender(); | |
} catch (error) { | |
// this allows to differentiate server vs client rendering | |
if (typeof window !== 'undefined') { | |
// used to avoid side-effects via setState() | |
this.hasError = true; | |
console.error('Error inside', this.getComponentName(), 'is', error); | |
} | |
return this.renderErrorView(); | |
} | |
} | |
// this method should be overridden in nested classes | |
protected safeRender(): React.ReactNode { | |
return ( | |
<span dangerouslySetInnerHTML={{ __html: `<!-- Component ${this.getComponentName()} is not implemented. -->` }} /> | |
); | |
} | |
protected renderErrorView() { | |
return ( | |
<span | |
dangerouslySetInnerHTML={{ | |
__html: `<!-- Error inside ${this.getComponentName()}. For more info, please, check the console."-->`, | |
}} | |
/> | |
); | |
} | |
protected getComponentName() { | |
return !!this.constructor.name ? this.constructor.name : 'component'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment