Skip to content

Commit

Permalink
fix: Prevent the Playground from crashing on a form error. (#3164)
Browse files Browse the repository at this point in the history
Co-authored-by: Heath C <[email protected]>
  • Loading branch information
nickgros and heath-freenome authored Oct 3, 2022
1 parent 33896dc commit 22772c7
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 59 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ it according to semantic versioning. For example, if your PR adds a breaking cha
should change the heading of the (upcoming) version to include a major version bump.
-->
# 5.0.0-beta.11

## @rjsf/playground
- Added an error boundary to prevent the entire app from crashing when an error is thrown by Form. See [#3164](https://github.com/rjsf-team/react-jsonschema-form/pull/3164) for closed issues.

# 5.0.0-beta.10

## @rjsf/antd
Expand Down
35 changes: 35 additions & 0 deletions packages/playground/src/ErrorBoundary.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}

/** Update state so the next render will show the fallback UI. */
static getDerivedStateFromError(error) {
return { hasError: true, error: error };
}

resetErrorBoundary = () => {
this.setState({ hasError: false, error: null });
}

/** You can render any custom fallback UI */
render() {
if (this.state.hasError) {
return (
<div className="alert alert-danger">
<p>The following error was encountered:</p>
<pre>{this.state.error.message}</pre>
<button className="btn" onClick={this.resetErrorBoundary}>
Refresh Form
</button>
</div>
);
}
return this.props.children;
}
}

export default ErrorBoundary;
122 changes: 63 additions & 59 deletions packages/playground/src/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { samples } from "./samples";
import "react-app-polyfill/ie11";
import Form, { withTheme } from "@rjsf/core";
import { shouldRender } from "@rjsf/utils";
import DemoFrame from "./DemoFrame";
import localValidator from "@rjsf/validator-ajv6";

import DemoFrame from "./DemoFrame";
import ErrorBoundary from "./ErrorBoundary";

const log = (type) => console.log.bind(console, type);
const toJson = (val) => JSON.stringify(val, null, 2);

Expand Down Expand Up @@ -547,66 +549,68 @@ class Playground extends Component {
)}
</div>
<div className="col-sm-5">
{this.state.form && (
<DemoFrame
head={
<React.Fragment>
<link
rel="stylesheet"
id="theme"
href={this.state.stylesheet || ""}
/>
{theme === "antd" && (
<div
dangerouslySetInnerHTML={{
__html:
document.getElementById("antd-styles-iframe")
.contentDocument.head.innerHTML,
}}
<ErrorBoundary>
{this.state.form && (
<DemoFrame
head={
<React.Fragment>
<link
rel="stylesheet"
id="theme"
href={this.state.stylesheet || ""}
/>
)}
</React.Fragment>
}
style={{
width: "100%",
height: 1000,
border: 0,
}}
theme={theme}
>
<FormComponent
{...templateProps}
liveValidate={liveSettings.validate}
disabled={liveSettings.disable}
readonly={liveSettings.readonly}
omitExtraData={liveSettings.omitExtraData}
liveOmit={liveSettings.liveOmit}
noValidate={liveSettings.noValidate}
schema={schema}
uiSchema={uiSchema}
formData={formData}
onChange={this.onFormDataChange}
noHtml5Validate={true}
onSubmit={({ formData }, e) => {
console.log("submitted formData", formData);
console.log("submit event", e);
window.alert("Form submitted");
}}
fields={{ geo: GeoPosition }}
customValidate={validate}
validator={validators[validator]}
onBlur={(id, value) =>
console.log(`Touched ${id} with value ${value}`)
}
onFocus={(id, value) =>
console.log(`Focused ${id} with value ${value}`)
{theme === "antd" && (
<div
dangerouslySetInnerHTML={{
__html:
document.getElementById("antd-styles-iframe")
.contentDocument.head.innerHTML,
}}
/>
)}
</React.Fragment>
}
transformErrors={transformErrors}
onError={log("errors")}
ref={this.playGroundForm}
/>
</DemoFrame>
)}
style={{
width: "100%",
height: 1000,
border: 0,
}}
theme={theme}
>
<FormComponent
{...templateProps}
liveValidate={liveSettings.validate}
disabled={liveSettings.disable}
readonly={liveSettings.readonly}
omitExtraData={liveSettings.omitExtraData}
liveOmit={liveSettings.liveOmit}
noValidate={liveSettings.noValidate}
schema={schema}
uiSchema={uiSchema}
formData={formData}
onChange={this.onFormDataChange}
noHtml5Validate={true}
onSubmit={({ formData }, e) => {
console.log("submitted formData", formData);
console.log("submit event", e);
window.alert("Form submitted");
}}
fields={{ geo: GeoPosition }}
customValidate={validate}
validator={validators[validator]}
onBlur={(id, value) =>
console.log(`Touched ${id} with value ${value}`)
}
onFocus={(id, value) =>
console.log(`Focused ${id} with value ${value}`)
}
transformErrors={transformErrors}
onError={log("errors")}
ref={this.playGroundForm}
/>
</DemoFrame>
)}
</ErrorBoundary>
</div>
<div className="col-sm-12">
<p style={{ textAlign: "center" }}>
Expand Down

0 comments on commit 22772c7

Please sign in to comment.