Skip to content
This repository has been archived by the owner on Jun 21, 2023. It is now read-only.

Commit

Permalink
Update layouts example to persist state across client-side transition…
Browse files Browse the repository at this point in the history
…s. (vercel#26706)

* Update layouts example

* Update examples/layout-component/components/layout.js

Co-authored-by: JJ Kasper <jj@jjsweb.site>
  • Loading branch information
leerob and ijjk committed Jun 29, 2021
1 parent 20229ce commit 93a32b3
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 40 deletions.
2 changes: 1 addition & 1 deletion examples/layout-component/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Layout component example

This example shows a very common use case when building websites where you need to repeat some sort of layout for all your pages. Our pages are: `home`, `about` and `contact` and they all share the same `<head>` settings, the `<nav>` and the `<footer>`. Further more, the title (and potentially other head elements) can be sent as a prop to the layout component so that it's customizable in all pages.
This example shows a very common use case when building websites where you need to repeat some sort of layout for all your pages. Our pages are: `home`, `about` and `contact` and they all share the same layout and sidebar.

## Preview

Expand Down
35 changes: 6 additions & 29 deletions examples/layout-component/components/layout.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,13 @@
import Link from 'next/link'
import Head from 'next/head'
import styles from './layout.module.css'

export default function Layout({
children,
title = 'This is the default title',
}) {
export default function Layout({ children }) {
return (
<div>
<>
<Head>
<title>{title}</title>
<meta charSet="utf-8" />
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<title>Layouts Example</title>
</Head>
<header>
<nav>
<Link href="/">
<a>Home</a>
</Link>{' '}
|
<Link href="/about">
<a>About</a>
</Link>{' '}
|
<Link href="/contact">
<a>Contact</a>
</Link>
</nav>
</header>

{children}

<footer>{'I`m here to stay'}</footer>
</div>
<main className={styles.main}>{children}</main>
</>
)
}
9 changes: 9 additions & 0 deletions examples/layout-component/components/layout.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.main {
display: flex;
height: calc(100vh - 64px);
background-color: white;
}

.main > section {
padding: 32px;
}
19 changes: 19 additions & 0 deletions examples/layout-component/components/sidebar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Link from 'next/link'
import styles from './sidebar.module.css'

export default function Sidebar() {
return (
<nav className={styles.nav}>
<input className={styles.input} placeholder="Search..." />
<Link href="/">
<a>Home</a>
</Link>
<Link href="/about">
<a>About</a>
</Link>
<Link href="/contact">
<a>Contact</a>
</Link>
</nav>
)
}
39 changes: 39 additions & 0 deletions examples/layout-component/components/sidebar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.nav {
height: 100%;
display: flex;
flex-direction: column;
width: 250px;
background-color: #fafafa;
padding: 32px;
border-right: 1px solid #eaeaea;
}

.nav > a {
margin: 8px 0;
text-decoration: none;
background: white;
border-radius: 4px;
font-size: 14px;
padding: 12px 16px;
text-transform: uppercase;
font-weight: 600;
letter-spacing: 0.025em;
color: #333;
border: 1px solid #eaeaea;
transition: all 0.125s ease;
}

.nav > a:hover {
background-color: #eaeaea;
}

.input {
margin: 32px 0;
text-decoration: none;
background: white;
border-radius: 4px;
border: 1px solid #eaeaea;
font-size: 14px;
padding: 8px 16px;
height: 28px;
}
12 changes: 12 additions & 0 deletions examples/layout-component/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#__next {
display: flex;
flex-direction: column;
min-height: 100vh;
}

body {
margin: 0;
font-size: 24px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
}
8 changes: 8 additions & 0 deletions examples/layout-component/pages/_app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import '../global.css'

export default function MyApp({ Component, pageProps }) {
// Use the layout defined at the page level, if available
const getLayout = Component.getLayout || ((page) => page)

return getLayout(<Component {...pageProps} />)
}
37 changes: 34 additions & 3 deletions examples/layout-component/pages/about.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
import Layout from '../components/layout'
import Sidebar from '../components/sidebar'

export default function About() {
return (
<Layout title="About us">
<div>About us</div>
</Layout>
<section>
<h2>Layout Example (About)</h2>
<p>
This example adds a property <code>getLayout</code> to your page,
allowing you to return a React component for the layout. This allows you
to define the layout on a per-page basis. Since we're returning a
function, we can have complex nested layouts if desired.
</p>
<p>
When navigating between pages, we want to persist page state (input
values, scroll position, etc) for a Single-Page Application (SPA)
experience.
</p>
<p>
This layout pattern will allow for state persistence because the React
component tree is persisted between page transitions. To preserve state,
we need to prevent the React component tree from being discarded between
page transitions.
</p>
<h3>Try It Out</h3>
<p>
To visualize this, try tying in the search input in the{' '}
<code>Sidebar</code> and then changing routes. You'll notice the input
state is persisted.
</p>
</section>
)
}

About.getLayout = (page) => (
<Layout>
<Sidebar />
{page}
</Layout>
)
37 changes: 34 additions & 3 deletions examples/layout-component/pages/contact.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
import Layout from '../components/layout'
import Sidebar from '../components/sidebar'

export default function Contact() {
return (
<Layout title="Contact us">
<div>Contact</div>
</Layout>
<section>
<h2>Layout Example (Contact)</h2>
<p>
This example adds a property <code>getLayout</code> to your page,
allowing you to return a React component for the layout. This allows you
to define the layout on a per-page basis. Since we're returning a
function, we can have complex nested layouts if desired.
</p>
<p>
When navigating between pages, we want to persist page state (input
values, scroll position, etc) for a Single-Page Application (SPA)
experience.
</p>
<p>
This layout pattern will allow for state persistence because the React
component tree is persisted between page transitions. To preserve state,
we need to prevent the React component tree from being discarded between
page transitions.
</p>
<h3>Try It Out</h3>
<p>
To visualize this, try tying in the search input in the{' '}
<code>Sidebar</code> and then changing routes. You'll notice the input
state is persisted.
</p>
</section>
)
}

Contact.getLayout = (page) => (
<Layout>
<Sidebar />
{page}
</Layout>
)
39 changes: 35 additions & 4 deletions examples/layout-component/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
import Layout from '../components/layout'
import Sidebar from '../components/sidebar'

export default function Home() {
export default function Index() {
return (
<Layout>
<div>Hello World.</div>
</Layout>
<section>
<h2>Layout Example (Index)</h2>
<p>
This example adds a property <code>getLayout</code> to your page,
allowing you to return a React component for the layout. This allows you
to define the layout on a per-page basis. Since we're returning a
function, we can have complex nested layouts if desired.
</p>
<p>
When navigating between pages, we want to persist page state (input
values, scroll position, etc) for a Single-Page Application (SPA)
experience.
</p>
<p>
This layout pattern will allow for state persistence because the React
component tree is persisted between page transitions. To preserve state,
we need to prevent the React component tree from being discarded between
page transitions.
</p>
<h3>Try It Out</h3>
<p>
To visualize this, try tying in the search input in the{' '}
<code>Sidebar</code> and then changing routes. You'll notice the input
state is persisted.
</p>
</section>
)
}

Index.getLayout = (page) => (
<Layout>
<Sidebar />
{page}
</Layout>
)

0 comments on commit 93a32b3

Please sign in to comment.