Skip to content

Commit

Permalink
examples: add RSC streaming pre-render with promise fallback example (#…
Browse files Browse the repository at this point in the history
…2905)

examples: add RSC streaming prerender with promise fallback example
  • Loading branch information
promer94 authored Mar 10, 2024
1 parent e4d3768 commit aa542a4
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 45 deletions.
Binary file added examples/suspense/app/favicon.ico
Binary file not shown.
9 changes: 9 additions & 0 deletions examples/suspense/app/layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function RootLayout({
children
}) {
return (
<html lang="en">
<body style={{ textAlign: 'center' }}>{children}</body>
</html>
)
}
4 changes: 4 additions & 0 deletions examples/suspense/app/rsc/[user]/[repo]/error.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use client'
export default function ErrorPage() {
return <div>Error happen</div>;
}
3 changes: 3 additions & 0 deletions examples/suspense/app/rsc/[user]/[repo]/loading.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Loading() {
return <div>Loading...</div>;
}
23 changes: 23 additions & 0 deletions examples/suspense/app/rsc/[user]/[repo]/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Repo from './repo'
import fetcher from '../../../../libs/fetch'
import Link from 'next/link'
import { Suspense } from 'react'
const Page = ({ params }) => {
const { user, repo } = params
const id = `${user}/${repo}`
const serverData = fetcher('http://localhost:3000/api/data?id=' + id)
return (
<div>
<div>Repo: {id}</div>
<Suspense fallback={<div>Loading stats</div>}>
<Repo serverData={serverData} id={id} />
</Suspense>
<br />
<br />
<Link href="/rsc">Back</Link>
</div>
)
}


export default Page
21 changes: 21 additions & 0 deletions examples/suspense/app/rsc/[user]/[repo]/repo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use client'
import fetcher from '../../../../libs/fetch'
import useSWR from 'swr'

const Repo = ({ id, serverData }) => {
const { data } = useSWR('/api/data?id=' + id, fetcher, { suspense: true, fallbackData: serverData })
return (
<>
{data ? (
<div>
<p>forks: {data.forks_count}</p>
<p>stars: {data.stargazers_count}</p>
<p>watchers: {data.watchers}</p>
</div>
) : null}

</>
)
}

export default Repo
3 changes: 3 additions & 0 deletions examples/suspense/app/rsc/loading.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Loading() {
return <div>Loading...</div>;
}
8 changes: 8 additions & 0 deletions examples/suspense/app/rsc/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import fetcher from '../../libs/fetch'
import Repos from './repos'
const Page = () => {
const serverData = fetcher('http://localhost:3000/api/data')
return <Repos serverData={serverData} />
}

export default Page
24 changes: 24 additions & 0 deletions examples/suspense/app/rsc/repos.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use client'
import useSWR from 'swr'
import fetcher from '../../libs/fetch'
import Link from 'next/link'

const Repos = ({ serverData }) => {
const { data } = useSWR('/api/data', fetcher, {
suspense: true,
fallbackData: serverData
})
return (
<>
{data.map(project => (
<p key={project}>
<Link href={`/rsc/${project}`}>
{project}
</Link>
</p>
))}
</>
)
}

export default Repos
6 changes: 6 additions & 0 deletions examples/suspense/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference types="next/navigation-types/compat/navigation" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
35 changes: 16 additions & 19 deletions examples/suspense/pages/[user]/[repo].js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ import { Suspense } from 'react'
import Link from 'next/link'
import fetcher from '../../libs/fetch'
import ErrorHandling from '../../components/error-handling'

import useSWR from 'swr'

const isServer = typeof window === 'undefined'

const Detail = ({ id }) => {
const { data } = useSWR('/api/data?id=' + id, fetcher, { suspense: true })
const Detail = ({ id, serverData }) => {
const { data } = useSWR('/api/data?id=' + id, fetcher, { suspense: true, fallbackData: serverData })

return (
<>
Expand All @@ -23,25 +20,25 @@ const Detail = ({ id }) => {
)
}

export default function Repo() {
const id =
typeof window !== 'undefined' ? window.location.pathname.slice(1) : ''

export default function Repo({ id, serverData }) {
return (
<div style={{ textAlign: 'center' }}>
<h1>{id}</h1>
{!isServer ? (
<Suspense fallback={<div>loading...</div>}>
<ErrorHandling fallback={<div>oooops!</div>}>
<Detail id={id}></Detail>
</ErrorHandling>
</Suspense>
) : null}
<Suspense fallback={<div>loading...</div>}>
<ErrorHandling fallback={<div>oooops!</div>}>
<Detail id={id} serverData={serverData}></Detail>
</ErrorHandling>
</Suspense>
<br />
<br />
<Link href="/">
Back
</Link>
<Link href="/">Back</Link>
</div>
)
}

export const getServerSideProps = async ({ params }) => {
const { user, repo } = params
const id = `${user}/${repo}`
const data = await fetcher('http://localhost:3000/api/data?id=' + id).catch(() => {})
return { props: { serverData: data, id } }
}
28 changes: 13 additions & 15 deletions examples/suspense/pages/api/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ export default function api(req, res) {
setTimeout(() => {
res.json({ msg: 'not found' })
})

return
} else {
// a slow endpoint for getting repo data
fetch(`https://api.github.com/repos/${req.query.id}`)
.then(res => res.json())
.then(data => {
setTimeout(() => {
res.json(data)
}, 2000)
})
}
// a slow endpoint for getting repo data
fetch(`https://api.github.com/repos/${req.query.id}`)
.then(res => res.json())
.then(data => {
setTimeout(() => {
res.json(data)
}, 2000)
})

return
} else {
setTimeout(() => {
res.json(projects)
}, 2000)
}
setTimeout(() => {
res.json(projects)
}, 2000)
}
26 changes: 15 additions & 11 deletions examples/suspense/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Suspense } from 'react'
import Link from 'next/link'
import fetcher from '../libs/fetch';
import fetcher from '../libs/fetch'

import useSWR from 'swr'

const isServer = typeof window === 'undefined'

const Repos = () => {
const { data } = useSWR('/api/data', fetcher, { suspense: true })
const Repos = ({ serverData }) => {
const { data } = useSWR('/api/data', fetcher, {
suspense: true,
fallbackData: serverData
})

return (
<>
Expand All @@ -22,15 +23,18 @@ const Repos = () => {
)
}

export default function Index() {
export default function Index({ serverData }) {
return (
<div style={{ textAlign: 'center' }}>
<h1>Trending Projects</h1>
{!isServer ? (
<Suspense fallback={<div>loading...</div>}>
<Repos></Repos>
</Suspense>
) : null}
<Suspense fallback={<div>loading...</div>}>
<Repos serverData={serverData}></Repos>
</Suspense>
</div>
)
}

export const getServerSideProps = async () => {
const data = await fetcher('http://localhost:3000/api/data')
return { props: { serverData: data } }
}

0 comments on commit aa542a4

Please sign in to comment.