npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@clearc2/c2-error

v2.0.0

Published

react error handling

Downloads

3

Readme

@clearc2/c2-error CircleCI

Provides a method to handle react component and ajax errors.

Install

# for yarn
yarn add @clearc2/c2-error

# for npm
npm install @clearc2/c2-error

Configure the package by:

  • setting the debug mode
  • returning any app related information at the time of error
  • supplying how errors should be reported(if at all)
  • add the ajax error interceptor
// src/c2-error-config.js
import {addErrorInterceptor, setConfig} from '@clearc2/c2-error'
import ajax from '../ajax'
import store from '../store'

setConfig({
  debug: ['staging', 'development'].includes(global.NODE_ENV),
  getInfo: () => {
    return {
      url: window.location.href,
      date: new Date(),
      loginId: store.getState().getIn(['Users', 'currentLoginId']),
      env: global.NODE_ENV
    }
  },
  reportAjaxError: (props) => {
    const {closeToast, ...error} = props
    return ajax.post('/api-error', {error}).then(closeToast)
  },
  reportComponentError: (props) => {
    const {closeToast, ...error} = props
    return new Promise(resolve => {
        window.location.href =
          `mailto:${global.errorEmail}` +
          `&subject=Runtime Error <project-name>` +
          `&body=${JSON.stringify(error, null, 4)}`
        closeToast()
        resolve()
    })
  }
})

addErrorInterceptor(ajax)

<ToastContainer /> and css

c2-error uses react-toastify to display error notifications. To display toasts, a <ToastContainer /> needs to be added to a root component that is always rendered regardless of route.

import {ToastContainer} from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'

function App () {
  return (
    <div className='main-content'>
      <ToastContainer />
      {/* other app stuff */}
    </div>
  )
}

Config

All fields are optional.

debug: bool

Determines whether or not to display debug information in the toast. Defaults to false.

getInfo: func

This should return any arbitrary information collected at the time the error occurs. Defaults to function that returns {url: window.location.href, date: new Date()}.

toastOptions: object

Default toast options. Defaults to {autoClose: false, closeOnClick: false}.

reportAjaxError: func

Must return a Promise. This function gets an object with the following keys: message, closeToast, info, error. closeToast is the function to programtically close the toast. error is the axios error object.

reportComponentError: func

Must return a Promise. This function gets an object with the following keys: message, closeToast, info, error, errorInfo, componentProps. error and errorInfo are what the error boundary catches. Read about these objects here. componentProps are the props that the underlying component received.

Usage

c2-error can handle two types of errors: component and ajax.

Component Errors

Use the onCatch higher-order component to provide a placeholder and toast message.

import React from 'react'
import {onCatch} from '@clearc2/c2-error'

function UserTable () {
  undefined.test() // intentional error
  return (
    <span>UserTable</span>
  )
}

export default onCatch({
  placeholder: 'Error :(',
  message: 'User table error'
})(UserTable)

// or customize the toast
export default onCatch({
  placeholder: 'Error :(',
  message: 'User table error',
  type: 'warn',
  options: {autoClose: true}
})(UserTable)

// or customize the message based on props or the error
export default onCatch({
  placeholder: 'Error :(',
  message: (props, error, errorInfo) => `User table error. User: ${props.loginId}`
})(UserTable)

The onCatch wraps the component in an error boundary. It does two things.

  1. Displays the placeholder instead of the component if it errors(UserTable in the example above)
  2. Creates a toast

Use the ifErrorsProp HOC to display a placeholder if the component receives an errors prop.

import {onCatch, ifErrorsProp} from '@clearc2/c2-error'

const enhance = compose(
  onCatch({placeholder: 'Error', message: 'User table error.'}),
  connect(userTableSelector, {fetchUsers}),
  ifErrorsProp({placeholder: 'Error'})
)

export default enhance(UserTable)

The onCatch HOC is meant to catch thrown javascript runtime errors using a React error boundary. The ifErrorsProp HOC displays a placeholder if errors are passed as a prop. For example, your component's redux selector can map in errors from a request(s).

The ifErrorsProp HOC is not meant to be used if the component is expecting errors to be passed to it. For example, with a form, it is very likely that users will enter invalid data and the api will respond with validation errors. Rather than replacing the whole form with a placeholder, the form will most likely want to render those errors above the inputs to allow the user to correct their input.

Ajax Errors

c2-error uses axios's config object to display errors if the request promise is rejected.

// use a simple error message
axios.get('/sites/123/tickets', {onError: `Error fetching site 123's tickets.`})

// or return a string based on the axios error
axios.get('/sites/123/tickets', {
  onError: (error) => {
    if (error.response.status === 404) {
      return `Couldn't find site 123's tickets.`
    }
    return `Error fetching site 123's tickets.`
  }
})

// or customize the toast by returning an object
axios.get('/sites/123/tickets', {
  onError: (error) => {
    return {
      message: `${error.response.status} - Error fetching site 123's tickets.`,
      type: 'warn',
      options: {
        autoClose: true
      }
    }
  }
})

Tips

Higher-order components can become awkward if several are used on the same component. Redux comes with a compose function that makes this less awkward.

import React from 'react'
import {compose} from 'redux'
import {connect} from 'react-redux'
import {onCatch, ifErrorsProp} from '@clearc2/c2-error'
import SitesTable from './SitesTable'
import selector from './selector'
import {fetchSites} from '../actions'

const enhance = compose(
  onCatch({placeholder: <BrokenIcon />, message: 'Sites table error'}),
  connect(selector, {fetchSites}),
  ifErrorsProp({placeholder: <BrokenIcon />})
)

export default enhance(SitesTable)

// the above is the same as this:
export default onCatch({placeholder: <BrokenIcon />, message: 'Sites table error'})(connect(selector, {fetchSites})(ifErrorsProp({placeholder: <BrokenIcon />})(UserTable)))