-
Notifications
You must be signed in to change notification settings - Fork 238
/
root.tsx
111 lines (98 loc) · 2.58 KB
/
root.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { withEmotionCache } from "@emotion/react";
import styled from "@emotion/styled";
import type { MetaFunction } from "@remix-run/node";
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
useCatch,
} from "@remix-run/react";
import { useContext, useEffect } from "react";
import ServerStyleContext from "./styles/server.context";
import ClientStyleContext from "./styles/client.context";
const Container = styled("div")`
background-color: #ff0000;
padding: 1em;
`;
export const meta: MetaFunction = () => ({
charset: "utf-8",
title: "Remix with Emotion",
viewport: "width=device-width,initial-scale=1",
});
interface DocumentProps {
children: React.ReactNode;
title?: string;
}
const Document = withEmotionCache(
({ children, title }: DocumentProps, emotionCache) => {
const serverStyleData = useContext(ServerStyleContext);
const clientStyleData = useContext(ClientStyleContext);
// Only executed on client
useEffect(() => {
// re-link sheet container
emotionCache.sheet.container = document.head;
// re-inject tags
const tags = emotionCache.sheet.tags;
emotionCache.sheet.flush();
tags.forEach((tag) => {
(emotionCache.sheet as any)._insertTag(tag);
});
// reset cache to re-apply global styles
clientStyleData.reset();
}, [clientStyleData, emotionCache.sheet]);
return (
<html lang="en">
<head>
{title ? <title>{title}</title> : null}
<Meta />
<Links />
{serverStyleData?.map(({ key, ids, css }) => (
<style
key={key}
data-emotion={`${key} ${ids.join(" ")}`}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: css }}
/>
))}
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}
);
export default function App() {
return (
<Document>
<Outlet />
</Document>
);
}
export function CatchBoundary() {
const caught = useCatch();
return (
<Document title={`${caught.status} ${caught.statusText}`}>
<Container>
<p>
[CatchBoundary]: {caught.status} {caught.statusText}
</p>
</Container>
</Document>
);
}
export function ErrorBoundary({ error }: { error: Error }) {
return (
<Document title="Error!">
<Container>
<p>[ErrorBoundary]: There was an error: {error.message}</p>
</Container>
</Document>
);
}