From 9cfd6968cb0f45ac2fafa40b3e5f2a57735bde7d Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Fri, 21 Apr 2023 13:40:53 -0400 Subject: [PATCH] Add error boundary to Flight fixture Errors in form actions are now rethrown during render (#26689), so we can handle the using an error boundary. --- fixtures/flight/src/Button.js | 37 +++++++++++++++------------- fixtures/flight/src/ErrorBoundary.js | 16 ++++++++++++ fixtures/flight/src/Form.js | 33 ++++++++++++++----------- 3 files changed, 54 insertions(+), 32 deletions(-) create mode 100644 fixtures/flight/src/ErrorBoundary.js diff --git a/fixtures/flight/src/Button.js b/fixtures/flight/src/Button.js index 78adf641139a..d4a3f8500eaf 100644 --- a/fixtures/flight/src/Button.js +++ b/fixtures/flight/src/Button.js @@ -1,27 +1,30 @@ 'use client'; import * as React from 'react'; +import {flushSync} from 'react-dom'; +import ErrorBoundary from './ErrorBoundary.js'; export default function Button({action, children}) { const [isPending, setIsPending] = React.useState(false); return ( -
- -
+ +
+ +
+
); } diff --git a/fixtures/flight/src/ErrorBoundary.js b/fixtures/flight/src/ErrorBoundary.js new file mode 100644 index 000000000000..44dc0965142e --- /dev/null +++ b/fixtures/flight/src/ErrorBoundary.js @@ -0,0 +1,16 @@ +'use client'; + +import * as React from 'react'; + +export default class ErrorBoundary extends React.Component { + state = {error: null}; + static getDerivedStateFromError(error) { + return {error}; + } + render() { + if (this.state.error) { + return
Caught an error: {this.state.error.message}
; + } + return this.props.children; + } +} diff --git a/fixtures/flight/src/Form.js b/fixtures/flight/src/Form.js index 8b1bb01ad0e0..8c2ff2922da1 100644 --- a/fixtures/flight/src/Form.js +++ b/fixtures/flight/src/Form.js @@ -1,25 +1,28 @@ 'use client'; import * as React from 'react'; +import {flushSync} from 'react-dom'; +import ErrorBoundary from './ErrorBoundary.js'; export default function Form({action, children}) { const [isPending, setIsPending] = React.useState(false); return ( -
{ - setIsPending(true); - try { - const result = await action(formData); - alert(result); - } catch (error) { - console.error(error); - } finally { - setIsPending(false); - } - }}> - - -
+ +
{ + // TODO: Migrate to useFormPending once that exists + flushSync(() => setIsPending(true)); + try { + const result = await action(formData); + alert(result); + } finally { + React.startTransition(() => setIsPending(false)); + } + }}> + + +
+
); }