Skip to content

Commit e4f4aa8

Browse files
authored
fix(Page): handle failed dynamic content loading safely (#8006)
1 parent dc78c56 commit e4f4aa8

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

src/components/Page/Page.jsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ export default function Page(props) {
3030
);
3131
const content = isDynamicContent
3232
? dynamicContent
33-
: props.content.default || props.content;
33+
: props.content && props.content.default !== undefined
34+
? props.content.default
35+
: props.content;
3436

3537
const [contentLoaded, setContentLoaded] = useState(!isDynamicContent);
3638

@@ -41,7 +43,13 @@ export default function Page(props) {
4143
setContent(() => mod.default || mod);
4244
setContentLoaded(true);
4345
})
44-
.catch(() => setContent("Error loading content."));
46+
.catch(() => {
47+
setContent({
48+
__error: true,
49+
message: "Failed to load page content.",
50+
});
51+
setContentLoaded(true);
52+
});
4553
}
4654
}, [props.content]);
4755

@@ -95,6 +103,10 @@ export default function Page(props) {
95103

96104
if (typeof content === "function") {
97105
contentRender = content({}).props.children;
106+
} else if (content && content.__error) {
107+
contentRender = (
108+
<div className="text-red-600 font-bold">{content.message}</div>
109+
);
98110
} else {
99111
contentRender = (
100112
<div
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* @jest-environment jsdom
3+
*/
4+
5+
import { render, screen } from "@testing-library/react";
6+
import { MemoryRouter } from "react-router-dom";
7+
import Page from "../Page.jsx";
8+
9+
jest.mock("../../Contributors/Contributors.jsx", () => {
10+
const MockContributors = () => <div />;
11+
return MockContributors;
12+
});
13+
14+
jest.mock("../../PageLinks/PageLinks.jsx", () => {
15+
const MockPageLinks = () => <div />;
16+
return MockPageLinks;
17+
});
18+
19+
jest.mock("react-router-dom", () => {
20+
const actual = jest.requireActual("react-router-dom");
21+
return {
22+
...actual,
23+
useLocation: () => ({ pathname: "/test", hash: "" }),
24+
};
25+
});
26+
27+
Object.defineProperty(window, "scrollTo", {
28+
value: jest.fn(),
29+
writable: true,
30+
});
31+
32+
describe("Page component", () => {
33+
it("renders error message when content.__error exists", async () => {
34+
const content = {
35+
__error: true,
36+
message: "Failed to load page content.",
37+
};
38+
39+
render(
40+
<MemoryRouter>
41+
<Page content={content} title="Test" path="/test" />
42+
</MemoryRouter>,
43+
);
44+
45+
const errorElement = await screen.findByText(
46+
/failed to load page content/i,
47+
);
48+
expect(errorElement).toBeTruthy();
49+
});
50+
});

0 commit comments

Comments
 (0)