UNPKG

@xysfe/catch-react-error

Version:

react error boundaries

76 lines (68 loc) 2.33 kB
import * as React from 'react' import { Component, forwardRef } from 'react' import DefaultErrorBoundary from './components/DefaultErrorBoundary' import { is_server, isComponentClass, isReactMemo } from './utils/index' const catchreacterror = (Boundary = DefaultErrorBoundary) => ((InnerComponent) => { if (Boundary && !Boundary.prototype.isReactComponent) { console.warn(`The ${Boundary} component is not a react component`); Boundary = DefaultErrorBoundary } if (Boundary && !(Boundary.prototype.componentDidCatch || Boundary.prototype.getDerivedStateFromError)) { console.warn(`${Boundary} doesn't has componentDidCatch or getDerivedStateFromError`); Boundary = DefaultErrorBoundary } // 将React.memo包裹过的组件转换成普通函数式组件 if (!isComponentClass(InnerComponent) && isReactMemo(InnerComponent)) { const NewComponent = InnerComponent; InnerComponent = function (props) { return <NewComponent {...props} /> } } if (isComponentClass(InnerComponent)) { if (is_server()) { const originalRender = InnerComponent.prototype.render InnerComponent.prototype.render = function () { try { return originalRender.apply(this, arguments); } catch (error) { console.error(error) return null } } } class WrapperComponent extends Component { render() { const { forwardedRef, } = this.props; return ( <Boundary > {isComponentClass(InnerComponent) ? <InnerComponent {...this.props} ref={forwardedRef} /> : <InnerComponent {...this.props} /> } </Boundary> ) } } return forwardRef((props, ref) => <WrapperComponent forwardedRef={ref} {...props} />) } else { if (is_server()) { const originalFun = InnerComponent; InnerComponent = function () { try { return originalFun.apply(null, arguments); } catch (error) { console.error(error) return null } } } return (props) => ( <Boundary > <InnerComponent {...props} /> </Boundary> ) } }) export default catchreacterror