Skip to content

Commit

Permalink
Update root files to use Layout Export (#2292)
Browse files Browse the repository at this point in the history
  • Loading branch information
michenly authored Jul 5, 2024
1 parent 6e42eee commit a5e03e2
Show file tree
Hide file tree
Showing 16 changed files with 220 additions and 253 deletions.
68 changes: 68 additions & 0 deletions .changeset/khaki-maps-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
'skeleton': patch
'@shopify/create-hydrogen': patch
---

Update root to use [Remix's Layout Export pattern](https://remix.run/docs/en/main/file-conventions/root#layout-export) and eliminate the use of `useLoaderData` in root.

The diff below showcase how you can make this refactor in existing application.

```diff
import {
Outlet,
- useLoaderData,
+ useRouteLoaderData,
} from '@remix-run/react';
-import {Layout} from '~/components/Layout';
+import {PageLayout} from '~/components/PageLayout';

-export default function App() {
+export function Layout({children}: {children?: React.ReactNode}) {
const nonce = useNonce();
- const data = useLoaderData<typeof loader>();
+ const data = useRouteLoaderData<typeof loader>('root');

return (
<html>
...
<body>
- <Layout {...data}>
- <Outlet />
- </Layout>
+ {data? (
+ <PageLayout {...data}>{children}</PageLayout>
+ ) : (
+ children
+ )}
</body>
</html>
);
}

+export default function App() {
+ return <Outlet />;
+}

export function ErrorBoundary() {
const rootData = useLoaderData<typeof loader>();

return (
- <html>
- ...
- <body>
- <Layout {...rootData}>
- <div className="route-error">
- <h1>Error</h1>
- ...
- </div>
- </Layout>
- </body>
- </html>
+ <div className="route-error">
+ <h1>Error</h1>
+ ...
+ </div>
);
}

```
5 changes: 5 additions & 0 deletions .changeset/purple-eggs-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/hydrogen': patch
---

Update virtual route to use Layout component in the root file.
49 changes: 17 additions & 32 deletions docs/shopify-dev/analytics-setup/js/app/root.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import favicon from './assets/favicon.svg';
import resetStyles from './styles/reset.css?url';
import appStyles from './styles/app.css?url';
import {Layout} from '~/components/Layout';
import {PageLayout} from '~/components/PageLayout';
// [START import-custom]
import {ThirdPartyAnalyticsIntegration} from '~/components/ThirdPartyAnalyticsIntegration';
// [END import-custom]
Expand Down Expand Up @@ -109,10 +109,10 @@ export async function loader({context}) {
);
}

export default function App() {
export function Layout({children}) {
const nonce = useNonce();
/** @type {LoaderReturnData} */
const data = useLoaderData();
const data = useRouteLoaderData<RootLoader>('root');

return (
<html lang="en">
Expand All @@ -131,9 +131,7 @@ export default function App() {
customData={{foo: 'bar'}}
>
{/* [END provider] */}
<Layout {...data}>
<Outlet />
</Layout>
<PageLayout {...data}>{children}</PageLayout>
{/* [START custom-component] */}
<ThirdPartyAnalyticsIntegration />
{/* [END custom-component] */}
Expand All @@ -147,11 +145,12 @@ export default function App() {
);
}

export default function App() {
return <Outlet />;
}

export function ErrorBoundary() {
const error = useRouteError();
/** @type {LoaderReturnData} */
const rootData = useLoaderData();
const nonce = useNonce();
let errorMessage = 'Unknown error';
let errorStatus = 500;

Expand All @@ -163,29 +162,15 @@ export function ErrorBoundary() {
}

return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Layout {...rootData}>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
</Layout>
<ScrollRestoration nonce={nonce} />
<Scripts nonce={nonce} />
</body>
</html>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
);
}

Expand Down
48 changes: 17 additions & 31 deletions docs/shopify-dev/analytics-setup/ts/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import favicon from './assets/favicon.svg';
import resetStyles from './styles/reset.css?url';
import appStyles from './styles/app.css?url';
import {Layout} from '~/components/Layout';
import {PageLayout} from '~/components/PageLayout';
// [START import-custom]
import {ThirdPartyAnalyticsIntegration} from '~/components/ThirdPartyAnalyticsIntegration';
// [END import-custom]
Expand Down Expand Up @@ -110,9 +110,9 @@ export async function loader({context}: LoaderFunctionArgs) {
);
}

export default function App() {
export function Layout({children}: {children?: React.ReactNode}) {
const nonce = useNonce();
const data = useLoaderData<typeof loader>();
const data = useRouteLoaderData<RootLoader>('root');

return (
<html lang="en">
Expand All @@ -131,9 +131,7 @@ export default function App() {
customData={{foo: 'bar'}}
>
{/* [END provider] */}
<Layout {...data}>
<Outlet />
</Layout>
<PageLayout {...data}>{children}</PageLayout>
{/* [START custom-component] */}
<ThirdPartyAnalyticsIntegration />
{/* [END custom-component] */}
Expand All @@ -147,10 +145,12 @@ export default function App() {
);
}

export default function App() {
return <Outlet />;
}

export function ErrorBoundary() {
const error = useRouteError();
const rootData = useLoaderData<typeof loader>();
const nonce = useNonce();
let errorMessage = 'Unknown error';
let errorStatus = 500;

Expand All @@ -162,29 +162,15 @@ export function ErrorBoundary() {
}

return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Layout {...rootData}>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
</Layout>
<ScrollRestoration nonce={nonce} />
<Scripts nonce={nonce} />
</body>
</html>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
);
}

Expand Down
28 changes: 11 additions & 17 deletions examples/b2b/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export async function loader({context}: LoaderFunctionArgs) {
});
}

function Layout({children}: {children?: React.ReactNode}) {
export function Layout({children}: {children?: React.ReactNode}) {
const nonce = useNonce();
const data = useRouteLoaderData<RootLoader>('root');

Expand Down Expand Up @@ -181,11 +181,7 @@ function Layout({children}: {children?: React.ReactNode}) {
}

export default function App() {
return (
<Layout>
<Outlet />
</Layout>
);
return <Outlet />;
}

export function ErrorBoundary() {
Expand All @@ -201,16 +197,14 @@ export function ErrorBoundary() {
}

return (
<Layout>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
</Layout>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
);
}
28 changes: 11 additions & 17 deletions examples/classic-remix/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function loadDeferredData({context}: LoaderFunctionArgs) {
};
}

function Layout({children}: {children?: React.ReactNode}) {
export function Layout({children}: {children?: React.ReactNode}) {
const nonce = useNonce();
const data = useRouteLoaderData<RootLoader>('root');

Expand Down Expand Up @@ -175,11 +175,7 @@ function Layout({children}: {children?: React.ReactNode}) {
}

export default function App() {
return (
<Layout>
<Outlet />
</Layout>
);
return <Outlet />;
}

export function ErrorBoundary() {
Expand All @@ -195,16 +191,14 @@ export function ErrorBoundary() {
}

return (
<Layout>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
</Layout>
<div className="route-error">
<h1>Oops</h1>
<h2>{errorStatus}</h2>
{errorMessage && (
<fieldset>
<pre>{errorMessage}</pre>
</fieldset>
)}
</div>
);
}
8 changes: 2 additions & 6 deletions examples/express/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export async function loader({context}: LoaderFunctionArgs) {
});
}

function Layout({children}: {children?: React.ReactNode}) {
export function Layout({children}: {children?: React.ReactNode}) {
const data = useRouteLoaderData<typeof loader>('root');
const nonce = useNonce();

Expand Down Expand Up @@ -96,11 +96,7 @@ function Layout({children}: {children?: React.ReactNode}) {
}

export default function App() {
return (
<Layout>
<Outlet />
</Layout>
);
return <Outlet />;
}

const CART_QUERY = `#graphql
Expand Down
Loading

0 comments on commit a5e03e2

Please sign in to comment.