Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
/**
 * @file this is for react error handling to help encapsulate errors
 *
 * @spec
 * https://github.com/v8/v8/wiki/Stack-Trace-API
 *
 * @discussions
 * https://github.com/facebook/react/issues/2461#issuecomment-158787924
 * https://github.com/facebook/react/pull/5615
 * https://github.com/skiano/react-safe-render/blob/feature/safe-methods/index.js
 * https://docs.google.com/document/d/1rda3yKGHimKIhg5YeoAmCOtyURgsbTH_qaYR79FELlk/edit#heading=h.sdpzjcyw06a5
 *
 * @libs
 * https://www.stacktracejs.com/
 * https://github.com/felixge/node-stack-trace
 */
import React from 'react'
import { stringify } from 'chain-able-boost'
import { isString, isEmpty, isFunction, EMPTY_OBJ } from 'exotic'
import { fromStringToStyle } from 'view-container'

// override of exotic
const isNotEmpty = x => isString(x) && !isEmpty(x) && x.trim() !== '.'

// @todo clean this out
let errorLines = 0
const toFormattedErrorLines = error => {
  const listItems = error
    .split(/((\n+)|(\.\s+))/)
    .filter(isNotEmpty)
    .map(line => {
      return (
        <li key={(errorLines += 1 + '@error')}>
          <small>{line}</small>
        </li>
      )
    })

  // is ordered but numbers don't work well
  return <ul>{listItems}</ul>
}
const styles = fromStringToStyle(`
  section {
    padding: 1rem;
  }

  ul {
    color: rgba(0, 0, 0, .3);
  }

  h2 {
    padding: 1rem;
    color: black;
    background-color: red;
  }

  pre {
    background-color: #fefefe;
    border: 2px solid #aeaeae;
    font: monospace;
  }
`)

/**
 * @tutorial https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html
 * @see https://github.com/commissure/redbox-react
 * @see https://github.com/bvaughn/react-error-boundary
 */
class ErrorBoundary extends React.Component {
  state = {
    hasError: false,
    error: undefined,
    stack: undefined,
  }

  componentDidCatch(error, info = EMPTY_OBJ) {
    const debugStack = isFunction(window.debuggable)
      ? window.debuggable(error)
      : error
    // const debugStack = window.debuggable.stackAt(7)
    const stack = stringify(debugStack, null, 2)

    console.warn(debugStack)
    console.log(error, info)

    this.setState({ hasError: true, error, stack, info })
  }

  render() {
    const { name } = this.props
    const { error, hasError, stack, info } = this.state

    if (hasError === true) {
      // JSON.stringify(error, null, 2)
      const errorView = error.message ? error.message : error.stack

      return (
        <div>
          {styles}
          <section>
            <h1>{name} Component Error</h1>
            <h2>PLEASE CHECK YOUR DEV CONSOLE</h2>
            <div>{toFormattedErrorLines(errorView)}</div>
            <pre>
              <code>{info.componentStack}</code>
            </pre>
            <pre>{stack}</pre>
          </section>
        </div>
      )
    }

    return this.props.children
  }
}

function withErrorBoundary() {
  return function withComponent(Component) {
    return function renderWithErrorBoundaryWithComponent(props) {
      return (
        <ErrorBoundary>
          <Component {...props} />
        </ErrorBoundary>
      )
    }
  }
}

export { withErrorBoundary }
export { ErrorBoundary }
export default ErrorBoundary