Skip to content

Commit

Permalink
refactor: convert error boundary code to Reason
Browse files Browse the repository at this point in the history
  • Loading branch information
anmonteiro committed Jun 10, 2024
1 parent 9da6b48 commit a6c9229
Showing 1 changed file with 52 additions and 22 deletions.
74 changes: 52 additions & 22 deletions src/ReasonReactErrorBoundary.re
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,62 @@ type params('error) = {
info,
};

[%%mel.raw
{|
var React = require("react");
var ErrorBoundary = (function (Component) {
function ErrorBoundary(props) {
Component.call(this);
this.state = {error: undefined};
};
ErrorBoundary.prototype = Object.create(Component.prototype);
ErrorBoundary.prototype.componentDidCatch = function(error, info) {
this.setState({error: {error: error, info: info}});
};
ErrorBoundary.prototype.render = function() {
return this.state.error != undefined
? this.props.fallback(this.state.error)
: this.props.children
};
return ErrorBoundary;
})(React.Component);
|}
];
[@mel.scope "Object"] external objCreate: 'a => Js.t({..}) = "create";

[@ocaml.warning "-69"]
type state('error) = {error: params('error)};
type reactComponentClass;

[@mel.module "react"] external component: reactComponentClass = "Component";
[@mel.send] external componentCall: (reactComponentClass, _) => unit = "call";

type componentPrototype;
[@mel.get]
external componentPrototype: reactComponentClass => componentPrototype =
"prototype";
[@mel.set] external setPrototype: (_, _) => unit = "prototype";

[@ocaml.warning "-21"]
let errorBoundary =
[@mel.this]
(
(self, _props) => (
{
componentCall(component, self);
self##state #= {"error": Js.undefined};
}: unit
)
);

setPrototype(errorBoundary, objCreate(componentPrototype(component)));

[@mel.set] [@mel.scope "prototype"]
external setComponentDidCatch:
(_, [@mel.this] (('self, 'error, 'info) => unit)) => unit =
"componentDidCatch";

setComponentDidCatch(errorBoundary, [@mel.this] (self, error, info) => {
self##setState({
error: {
error,
info,
},
})
});

[@mel.set] [@mel.scope "prototype"]
external setRender: (_, [@mel.this] ('self => unit)) => unit = "render";
setRender(errorBoundary, [@mel.this] self => {
switch (Js.Undefined.testAny(self##state##error)) {
| false => self##props##fallback(self##state##error)
| true => self##props##children
}
});

[@react.component]
external make:
(~children: React.element, ~fallback: params('error) => React.element) =>
React.element =
"ErrorBoundary";
"errorBoundary";

let make = make;

0 comments on commit a6c9229

Please sign in to comment.