Skip to content

Commit 8d059fa

Browse files
authored
Prevent errors in React components from crashing the dev server (#4816)
* Prevent errors in React components from crashing the dev server * Add a changeset * Fix test when running in the build
1 parent 57ea549 commit 8d059fa

6 files changed

Lines changed: 48 additions & 1 deletion

File tree

.changeset/tricky-walls-walk.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/react': patch
3+
---
4+
5+
Prevent errors in React components from crashing the dev server
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import ThrowsAnError from "./ThrowsAnError";
2+
3+
export default function() {
4+
return <>
5+
<ThrowsAnError />
6+
</>
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { useState } from 'react';
2+
3+
export default function() {
4+
let player = undefined;
5+
// This is tested in dev mode, so make it work during the build to prevent
6+
// breaking other tests.
7+
if(import.meta.env.MODE === 'production') {
8+
player = {};
9+
}
10+
const [] = useState(player.currentTime || null);
11+
12+
return (
13+
<div>Should have thrown</div>
14+
)
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
import ImportsThrowsAnError from '../components/ImportsThrowsAnError';
3+
---
4+
<html>
5+
<head>
6+
<title>Testing</title>
7+
</head>
8+
<body>
9+
<ImportsThrowsAnError />
10+
</body>
11+
</html>

packages/astro/test/react-component.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ describe('React Components', () => {
9494
if (isWindows) return;
9595

9696
describe('dev', () => {
97+
/** @type {import('./test-utils').Fixture} */
9798
let devServer;
9899

99100
before(async () => {
@@ -145,5 +146,10 @@ describe('React Components', () => {
145146
// test 1: react/jsx-runtime is used for the component
146147
expect(jsxRuntime).to.be.ok;
147148
});
149+
150+
it('When a nested component throws it does not crash the server', async () => {
151+
const res = await fixture.fetch('/error-rendering');
152+
await res.arrayBuffer();
153+
});
148154
});
149155
});

packages/integrations/react/server.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,11 @@ async function renderToPipeableStreamAsync(vnode) {
121121
async function renderToStaticNodeStreamAsync(vnode) {
122122
const Writable = await getNodeWritable();
123123
let html = '';
124-
return new Promise((resolve) => {
124+
return new Promise((resolve, reject) => {
125125
let stream = ReactDOM.renderToStaticNodeStream(vnode);
126+
stream.on('error', err => {
127+
reject(err);
128+
});
126129
stream.pipe(
127130
new Writable({
128131
write(chunk, _encoding, callback) {

0 commit comments

Comments
 (0)