continuing prior work from https://github.com/sw-yx/sw-yx.github.io/blob/master/_posts/2018-02-05-react-catch-error-prelim-work.md

first i need to deconstruct react-error-overlay.

then i should check out react dev utils:

and other react issues:


ok its 7.15pm and i am looking into react-error-overlay.

react error overlay deals with 2 kinds of errors: webpack build errors and runtime errors. at it’s core is an update function that gets run whenever you touch one of the 5 api’s below. it then creates an iframe to render your thing, and then goes away when you tell it to.

the entire API is encapsulated within this index.js:

  • setEditorHandler
  • dismissBuildError
  • reportBuildError
  • startReportingRuntimeErrors
  • stopReportingRuntimeErrors

the only other dependency is errorOverlayMiddleware which is super small. i used to think this was a necessary part of react-error-overlay but this was wrong.

now to investigate the 5 api’s. this is helped by having a clear usage example in webpackHotDevClient. i will refer to this as WHDC.

setEditorHandler receives a callback. this callback will be called in updateIframeContent() but it can easily be null since in WHDC the only usage is to sync with errorOverlayMiddleware.

Then there are two build error api’s.

reportBuildError is a synchronous function. you feed it a string and react-error-overlay displays it. you can’t use it without also supplying options to startReportingRuntimeErrors (below)

dismissBuildError undoes that and set it to null.

so when you use react-error-overlay, you can mock up whatever UI you want and then just control it with those two functions alone.

but build errors are not the only kind of errors.

startReportingRuntimeErrors takes an options object:

type RuntimeReportingOptions = {|
  onError: () => void,
  filename?: string,
|};

onError is a callback that runs if listenToRuntimeErrors https://github.com/facebook/create-react-app/blob/next/packages/react-error-overlay/src/listenToRuntimeErrors.js sees a crash (but this is all internal and you shouldnt have to set it up). WHDC just uses it to help forcibly reload the entire application (the comments point to this issue which i have not explored).

filename is the more interesting one. this looks like a pointer to the bundle with a sourcemap. it would be interesting to set this but it doesnt seem strictly necssary? we shall see.

stopReportingRuntimeErrors just helps you stop listening to stuff i guess. (“why do we need this” comment)


now on to try it in a sample CRA app.


operation was a success. this gets R-E-O running easily on a react app:

import React, { Component } from "react";
import {
  startReportingRuntimeErrors,
  stopReportingRuntimeErrors
} from "react-error-overlay";

const asyncerr = x => {
  return new Promise(res => {
    throw new Error("example error" + x);
  });
};
const BuggyButton = () => (
  <button
    onClick={() => {
      throw new Error("example error");
    }}
  >
    Test Error Overlay
  </button>
);
const BuggyButton5 = () => (
  <button
    onClick={() => {
      asyncerr(1);
      asyncerr(2);
      asyncerr(3);
      asyncerr(4);
      asyncerr(5);
    }}
  >
    Test Error Overlay 5 times
  </button>
);
class Plain extends Component {
  componentDidMount() {
    startReportingRuntimeErrors({ onError: () => {} });
  }
  componentWillUnmount() {
    stopReportingRuntimeErrors();
  }
  render() {
    return (
      <div>
        <p>Testing react-error-overlay</p>
        <ul>
          <li>
            <BuggyButton />
          </li>
          <li>
            <BuggyButton5 />
          </li>
        </ul>
      </div>
    );
  }
}

export default Plain;

but the package as a whole is 265kb (790kb gzip). acemarke wanted something better: https://twitter.com/acemarke/status/960330659414732800

this involves diving into listenToRuntimeErrors.


ok after diving in, it seems mark’s original recs were spot on but i paused here becuase there was no further need.

image