Skip to content

Commit

Permalink
add RFC-229 based way with use and Suspense for data fetching (#62)
Browse files Browse the repository at this point in the history
Co-authored-by: lowsky <lowsky@users.noreply.github.com>
  • Loading branch information
lowsky and lowsky authored Apr 2, 2023
1 parent d9445f8 commit 7e8ebb5
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 21 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
"eslint-config-next": "13.2.4",
"next": "13.2.4",
"prettier": "2.8.7",
"react": "18.2.0",
"react-dom": "18.2.0",
"react": "^18.3.0-next",
"react-dom": "^18.3.0-next",
"typescript": "4.9.5"
},
"packageManager": "yarn@3.5.0"
Expand Down
21 changes: 18 additions & 3 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Heading } from '@chakra-ui/react';
import { Box, Heading, UnorderedList } from '@chakra-ui/react';
import Head from 'next/head';

import InternalLink from '../components/InternalLink';
Expand All @@ -14,7 +14,22 @@ export default function Index() {

<Heading>What is it?</Heading>

<ul>
<Box>This is a demo of React.Suspense in data fetching scenarios.</Box>
<Box>
Main use case is typically showing a loading spinner.
<br />
Suspense helps to simplify the code structure for handling asynchronously data fetched even when it is
done incrementally.
</Box>

<Heading size="medium">Choose one of these different scenarios:</Heading>

<UnorderedList>
<li>
🆕<InternalLink href={'/next'}>Experimental, RFC-229</InternalLink>{' '}
<strong>use(await fetch)</strong> Fetching all data and use latest support of async data fetching
via `const data = use(await fetch)`
</li>
<li>
<InternalLink href={'/restful'}>Old way</InternalLink> <strong>All or nothing:</strong> Fetching all
data in a top-level `useEffect()` + props-drilling
Expand All @@ -31,7 +46,7 @@ export default function Index() {
<InternalLink href={'/side-by-side'}>Side-by-Side</InternalLink> <strong>Comparison:</strong> Show
incrementally loading and wait-for-all
</li>
</ul>
</UnorderedList>
</div>
);
}
69 changes: 69 additions & 0 deletions pages/next/[userName]/[repoName].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use client';
import React, { use, Suspense, cache } from 'react';

import { fetchRepoBranchesWithCommitStatusesAndPullRequests, fetchUser, User } from '../../../restinpeace/github';
import { UserRepoFromUrlProvider, useUserRepo } from '../../../components/useUserRepoFromRoute';
import UserRepo from '../../../container/UserRepo';
import RichErrorBoundary from '../../../components/RichErrorBoundary';
import InternalLink from '../../../components/InternalLink';
import { Spinner } from '../../../components/Spinner';
import { RepoType } from '../../../components/Repo';

function delay(timeout) {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
}

export default function ReactNextDrivenPage() {
return (
<UserRepoFromUrlProvider>
<ReactNextWithUrlContext />
</UserRepoFromUrlProvider>
);
}

function ReactNextWithUrlContext() {
const { userName, repoName } = useUserRepo();
const userData: Promise<User> = fetchUserPromise(userName);
const repoData: Promise<RepoType> = fetchRepoBranches({ userName, repoName });
return (
<UserRepoFromUrlProvider>
<RichErrorBoundary>
<InternalLink href={'/next'}>back to repos</InternalLink>
<Suspense fallback={<Spinner />}>
<ReactNext userData={userData} repoData={repoData} />
</Suspense>
</RichErrorBoundary>
</UserRepoFromUrlProvider>
);
}

const fetchUserPromise: (id) => Promise<User> = cache(async (id) => {
await delay(2000);
return fetchUser(id);
});
const fetchRepoBranches: ({ userName, repoName }) => Promise<RepoType> = cache(async ({ userName, repoName }) => {
await delay(2000);
return fetchRepoBranchesWithCommitStatusesAndPullRequestsProm({ userName, repoName });
});

interface Props {
userData: Promise<User>;
repoData: Promise<RepoType>;
}

function ReactNext({ userData, repoData }: Props) {
const user = use(userData);
const repo: RepoType = use(repoData);

return <UserRepo user={user} repo={repo} />;
}

const fetchRepoBranchesWithCommitStatusesAndPullRequestsProm = cache(async ({ userName, repoName }) =>
fetchRepoBranchesWithCommitStatusesAndPullRequests({ userName, repoName }).then((branchesWithCommit) => ({
name: repoName,
owner: { login: userName },
branches: branchesWithCommit.branches,
}))
);
27 changes: 27 additions & 0 deletions pages/next/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client'; // this directive should be at top of the file, before any imports.

import React from 'react';
import { Box, Heading, Link } from '@chakra-ui/react';

import InternalLink from '../../components/InternalLink';
import { LinkList } from '../../components/LinkList';

export default function Shortcuts() {
return (
<div>
<InternalLink href={'/'}>back to main page</InternalLink>

<Heading>Experimental, RFC-229</Heading>
<Box mb={6}>
<strong>use(await fetch)</strong> Fetching all data and use latest support of async data fetching via
`const data = use(await fetch)`
</Box>
<Box mb={6}>
See <Link href="https://github.com/reactjs/rfcs/pull/229">GH/reactjs/rfcs/pull/229</Link> for mor
details
</Box>

<LinkList rootPath="/next" />
</div>
);
}
32 changes: 16 additions & 16 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4318,15 +4318,15 @@ __metadata:
languageName: node
linkType: hard

"react-dom@npm:18.2.0":
version: 18.2.0
resolution: "react-dom@npm:18.2.0"
"react-dom@npm:^18.3.0-next":
version: 18.3.0-next-fecc288b7-20221025
resolution: "react-dom@npm:18.3.0-next-fecc288b7-20221025"
dependencies:
loose-envify: ^1.1.0
scheduler: ^0.23.0
scheduler: 0.24.0-next-fecc288b7-20221025
peerDependencies:
react: ^18.2.0
checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc
react: 18.3.0-next-fecc288b7-20221025
checksum: bee2c161c37498974816abaf191767186473422d7642f7b333c039a046a0c1d724bc7a1482d714a9fff0f95287ee62909f2e903837a966a2fde1bca50fbf0c45
languageName: node
linkType: hard

Expand Down Expand Up @@ -4454,19 +4454,19 @@ __metadata:
hitchcock: 0.5.0
next: 13.2.4
prettier: 2.8.7
react: 18.2.0
react: ^18.3.0-next
react-cache: latest
react-dom: 18.2.0
react-dom: ^18.3.0-next
typescript: 4.9.5
languageName: unknown
linkType: soft

"react@npm:18.2.0":
version: 18.2.0
resolution: "react@npm:18.2.0"
"react@npm:^18.3.0-next":
version: 18.3.0-next-fecc288b7-20221025
resolution: "react@npm:18.3.0-next-fecc288b7-20221025"
dependencies:
loose-envify: ^1.1.0
checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b
checksum: 860e2a595be0f3c75707ae4850490b367f1e6fb4275c1af9a33f234a9d47d9202ad49c51366a3b9d43d145c6fe106dde1089d93d7227efaadcaa4b8432122cb7
languageName: node
linkType: hard

Expand Down Expand Up @@ -4592,12 +4592,12 @@ __metadata:
languageName: node
linkType: hard

"scheduler@npm:^0.23.0":
version: 0.23.0
resolution: "scheduler@npm:0.23.0"
"scheduler@npm:0.24.0-next-fecc288b7-20221025":
version: 0.24.0-next-fecc288b7-20221025
resolution: "scheduler@npm:0.24.0-next-fecc288b7-20221025"
dependencies:
loose-envify: ^1.1.0
checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a
checksum: c51ecea03ce23c2cb27bfd6c0bb350722a6d7d9d692e43d195f0397fe29ce19f87e9f1a58939eab89b2535f1b87f45c52b898f3cfe2b5eeb1c78a6a97d53c117
languageName: node
linkType: hard

Expand Down

1 comment on commit 7e8ebb5

@vercel
Copy link

@vercel vercel bot commented on 7e8ebb5 Apr 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.