Skip to content

Commit

Permalink
docs: add example of dynamic layout with static page (#922)
Browse files Browse the repository at this point in the history
you can see the time change as navigating the site which shows that the
layout is indeed dynamic

The rest of the home page stays unchanged and can be cached

Example for #885

---------

Co-authored-by: Tyler <[email protected]>
  • Loading branch information
tylersayshi and tylersayshi authored Oct 3, 2024
1 parent c946a30 commit 5e183b8
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 0 deletions.
23 changes: 23 additions & 0 deletions examples/25_weave_render/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "waku-example",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
"dev": "waku dev",
"build": "waku build",
"start": "waku start"
},
"dependencies": {
"react": "19.0.0-rc-d6cb4e77-20240911",
"react-dom": "19.0.0-rc-d6cb4e77-20240911",
"react-server-dom-webpack": "19.0.0-rc-d6cb4e77-20240911",
"waku": "0.21.2"
},
"devDependencies": {
"@types/react": "18.3.5",
"@types/react-dom": "18.3.0",
"server-only": "0.0.1",
"typescript": "5.6.2"
}
}
64 changes: 64 additions & 0 deletions examples/25_weave_render/src/components/BarLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { ReactNode } from 'react';

import { Link } from 'waku/router/client';

import '../styles.css';

const Pending = ({ isPending }: { isPending: boolean }) => (
<span
style={{
marginLeft: 5,
transition: 'opacity 75ms 100ms',
opacity: isPending ? 1 : 0,
}}
>
Pending...
</span>
);

const BarLayout = ({ children }: { children: ReactNode }) => {
return (
<html>
<head>
<title>Waku</title>
</head>
<body>
<div>
<p>This Layout is expected to be static</p>
<ul>
<li>
<Link
to="/"
pending={<Pending isPending />}
notPending={<Pending isPending={false} />}
>
Home
</Link>
</li>
<li>
<Link
to="/foo"
pending={<Pending isPending />}
notPending={<Pending isPending={false} />}
>
Foo
</Link>
</li>
<li>
<Link
to="/nested/bar"
pending={<Pending isPending />}
notPending={<Pending isPending={false} />}
>
Nested / Bar
</Link>
</li>
</ul>
{children}
</div>
</body>
</html>
);
};

export default BarLayout;
10 changes: 10 additions & 0 deletions examples/25_weave_render/src/components/BarPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Counter } from './Counter';

const Bar = () => (
<div>
<h2>Bar</h2>
<Counter />
</div>
);

export default Bar;
19 changes: 19 additions & 0 deletions examples/25_weave_render/src/components/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use client';

import { useState } from 'react';

import { Link, useRouter_UNSTABLE as useRouter } from 'waku/router/client';

export const Counter = () => {
const { path } = useRouter();
const [count, setCount] = useState(0);
return (
<div style={{ border: '3px blue dashed', margin: '1em', padding: '1em' }}>
<p>Count: {count}</p>
<button onClick={() => setCount((c) => c + 1)}>Increment</button>
<h3>This is a client component.</h3>
<span>path: {path}</span>
<Link to="/">Go to Home</Link>
</div>
);
};
16 changes: 16 additions & 0 deletions examples/25_weave_render/src/components/FooLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { ReactNode } from 'react';

const FooLayout = ({ children }: { children: ReactNode }) => {
return (
<html>
<body>
<div>
<h1>FOO layout</h1>
{children}
</div>
</body>
</html>
);
};

export default FooLayout;
12 changes: 12 additions & 0 deletions examples/25_weave_render/src/components/FooPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'server-only';

import { Counter } from './Counter';

const Foo = () => (
<div>
<h2>Foo</h2>
<Counter />
</div>
);

export default Foo;
68 changes: 68 additions & 0 deletions examples/25_weave_render/src/components/HomeLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { ReactNode } from 'react';

import { Link } from 'waku/router/client';

import '../styles.css';

const Pending = ({ isPending }: { isPending: boolean }) => (
<span
style={{
marginLeft: 5,
transition: 'opacity 75ms 100ms',
opacity: isPending ? 1 : 0,
}}
>
Pending...
</span>
);

const getCurrentTime = () => new Date();

const HomeLayout = ({ children }: { children: ReactNode }) => {
const currentTime = getCurrentTime();
return (
<html>
<head>
<title>Waku</title>
</head>
<body>
<div>
<h1>Home layout</h1>
<p>Last render time: {currentTime.toISOString()}</p>
<ul>
<li>
<Link
to="/"
pending={<Pending isPending />}
notPending={<Pending isPending={false} />}
>
Home
</Link>
</li>
<li>
<Link
to="/foo"
pending={<Pending isPending />}
notPending={<Pending isPending={false} />}
>
Foo
</Link>
</li>
<li>
<Link
to="/nested/bar"
pending={<Pending isPending />}
notPending={<Pending isPending={false} />}
>
Nested / Bar
</Link>
</li>
</ul>
{children}
</div>
</body>
</html>
);
};

export default HomeLayout;
8 changes: 8 additions & 0 deletions examples/25_weave_render/src/components/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const Home = () => (
<div>
<h2>Home</h2>
<p>This is the home page.</p>
</div>
);

export default Home;
57 changes: 57 additions & 0 deletions examples/25_weave_render/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { lazy } from 'react';
import { createPages } from 'waku';
import type { PathsForPages } from 'waku/router';
import FooPage from './components/FooPage';
import BarPage from './components/BarPage';
import BarLayout from './components/BarLayout';
import FooLayout from './components/FooLayout';

// The use of `lazy` is optional and you can use import statements too.
const HomeLayout = lazy(() => import('./components/HomeLayout'));
const HomePage = lazy(() => import('./components/HomePage'));

const pages = createPages(async ({ createPage, createLayout }) => [
createLayout({
render: 'static',
path: '/',
component: HomeLayout,
}),

createPage({
render: 'static',
path: '/',
component: HomePage,
}),

createLayout({
render: 'static',
path: '/foo',
component: FooLayout,
}),

createPage({
render: 'dynamic',
path: '/foo',
component: FooPage,
}),

createLayout({
render: 'dynamic',
path: '/bar',
component: BarLayout,
}),

createPage({
render: 'static',
path: '/bar',
component: BarPage,
}),
]);

declare module 'waku/router' {
interface RouteConfig {
paths: PathsForPages<typeof pages>;
}
}

export default pages;
15 changes: 15 additions & 0 deletions examples/25_weave_render/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Router } from 'waku/router/client';

const rootElement = (
<StrictMode>
<Router />
</StrictMode>
);

if ((globalThis as any).__WAKU_HYDRATE__) {
hydrateRoot(document, rootElement);
} else {
createRoot(document as any).render(rootElement);
}
3 changes: 3 additions & 0 deletions examples/25_weave_render/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
background-color: #fefefe;
}
15 changes: 15 additions & 0 deletions examples/25_weave_render/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"strict": true,
"target": "esnext",
"downlevelIteration": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"types": ["react/experimental"],
"jsx": "react-jsx"
}
}
28 changes: 28 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5e183b8

Please sign in to comment.