diff --git a/examples/suspense/app/favicon.ico b/examples/suspense/app/favicon.ico new file mode 100644 index 000000000..4570eb8d9 Binary files /dev/null and b/examples/suspense/app/favicon.ico differ diff --git a/examples/suspense/app/layout.jsx b/examples/suspense/app/layout.jsx new file mode 100644 index 000000000..659980d8d --- /dev/null +++ b/examples/suspense/app/layout.jsx @@ -0,0 +1,9 @@ +export default function RootLayout({ + children +}) { + return ( + + {children} + + ) +} diff --git a/examples/suspense/app/rsc/[user]/[repo]/error.jsx b/examples/suspense/app/rsc/[user]/[repo]/error.jsx new file mode 100644 index 000000000..d26979655 --- /dev/null +++ b/examples/suspense/app/rsc/[user]/[repo]/error.jsx @@ -0,0 +1,4 @@ +'use client' +export default function ErrorPage() { + return
Error happen
; +} \ No newline at end of file diff --git a/examples/suspense/app/rsc/[user]/[repo]/loading.jsx b/examples/suspense/app/rsc/[user]/[repo]/loading.jsx new file mode 100644 index 000000000..ac709eb97 --- /dev/null +++ b/examples/suspense/app/rsc/[user]/[repo]/loading.jsx @@ -0,0 +1,3 @@ +export default function Loading() { + return
Loading...
; +} \ No newline at end of file diff --git a/examples/suspense/app/rsc/[user]/[repo]/page.jsx b/examples/suspense/app/rsc/[user]/[repo]/page.jsx new file mode 100644 index 000000000..762190dcb --- /dev/null +++ b/examples/suspense/app/rsc/[user]/[repo]/page.jsx @@ -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 ( +
+
Repo: {id}
+ Loading stats
}> + + +
+
+ Back + + ) +} + + +export default Page \ No newline at end of file diff --git a/examples/suspense/app/rsc/[user]/[repo]/repo.jsx b/examples/suspense/app/rsc/[user]/[repo]/repo.jsx new file mode 100644 index 000000000..a87c8df0f --- /dev/null +++ b/examples/suspense/app/rsc/[user]/[repo]/repo.jsx @@ -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 ? ( +
+

forks: {data.forks_count}

+

stars: {data.stargazers_count}

+

watchers: {data.watchers}

+
+ ) : null} + + + ) +} + +export default Repo \ No newline at end of file diff --git a/examples/suspense/app/rsc/loading.jsx b/examples/suspense/app/rsc/loading.jsx new file mode 100644 index 000000000..ac709eb97 --- /dev/null +++ b/examples/suspense/app/rsc/loading.jsx @@ -0,0 +1,3 @@ +export default function Loading() { + return
Loading...
; +} \ No newline at end of file diff --git a/examples/suspense/app/rsc/page.jsx b/examples/suspense/app/rsc/page.jsx new file mode 100644 index 000000000..a6df667a6 --- /dev/null +++ b/examples/suspense/app/rsc/page.jsx @@ -0,0 +1,8 @@ +import fetcher from '../../libs/fetch' +import Repos from './repos' +const Page = () => { + const serverData = fetcher('http://localhost:3000/api/data') + return +} + +export default Page diff --git a/examples/suspense/app/rsc/repos.jsx b/examples/suspense/app/rsc/repos.jsx new file mode 100644 index 000000000..557641844 --- /dev/null +++ b/examples/suspense/app/rsc/repos.jsx @@ -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 => ( +

+ + {project} + +

+ ))} + + ) +} + +export default Repos \ No newline at end of file diff --git a/examples/suspense/next-env.d.ts b/examples/suspense/next-env.d.ts new file mode 100644 index 000000000..fd36f9494 --- /dev/null +++ b/examples/suspense/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/suspense/pages/[user]/[repo].js b/examples/suspense/pages/[user]/[repo].js index e7fef9f7f..178762d4d 100644 --- a/examples/suspense/pages/[user]/[repo].js +++ b/examples/suspense/pages/[user]/[repo].js @@ -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 ( <> @@ -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 (

{id}

- {!isServer ? ( - loading...
}> - oooops!}> - - - - ) : null} + loading...}> + oooops!}> + + +

- - Back - + Back ) } + +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 } } +} \ No newline at end of file diff --git a/examples/suspense/pages/api/data.js b/examples/suspense/pages/api/data.js index 5bc3ab502..c0ef97162 100644 --- a/examples/suspense/pages/api/data.js +++ b/examples/suspense/pages/api/data.js @@ -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) } diff --git a/examples/suspense/pages/index.js b/examples/suspense/pages/index.js index e94b75451..2671e9974 100644 --- a/examples/suspense/pages/index.js +++ b/examples/suspense/pages/index.js @@ -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 ( <> @@ -22,15 +23,18 @@ const Repos = () => { ) } -export default function Index() { +export default function Index({ serverData }) { return (

Trending Projects

- {!isServer ? ( - loading...
}> - - - ) : null} + loading...}> + + ) } + +export const getServerSideProps = async () => { + const data = await fetcher('http://localhost:3000/api/data') + return { props: { serverData: data } } +}