Skip to content

Commit

Permalink
Reproduce issue vercel/next.js#44083
Browse files Browse the repository at this point in the history
  • Loading branch information
phuctm97 committed Feb 3, 2023
1 parent fa76ef0 commit bc90ef3
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 42 deletions.
31 changes: 31 additions & 0 deletions components/example/component.tsx
@@ -0,0 +1,31 @@
import styles from "@/styles/Home.module.css";

import Image from "next/image";
import { atom, useRecoilValue } from "recoil";

const componentAtom = atom<void>({
key: "component",
default: new Promise((resolve) => setTimeout(resolve, 5000)), // Example data fetching or async operation
});

export default function Component() {
// This will suspend the component
// Recoil is being used just to demonstrate the issue happen when this component being suspended
// If you use React Developer Tools to suspend this component manually, the issue will still happen
useRecoilValue(componentAtom);
return (
<div className={styles.center}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
<div className={styles.thirteen}>
<Image src="/thirteen.svg" alt="13" width={40} height={31} priority />
</div>
</div>
);
}
9 changes: 9 additions & 0 deletions components/example/fallback.tsx
@@ -0,0 +1,9 @@
import styles from "@/styles/Home.module.css";

export function Fallback() {
return (
<div className={`${styles.center} ${styles.description}`}>
<p>Loading…</p>
</div>
);
}
22 changes: 22 additions & 0 deletions components/example/index.tsx
@@ -0,0 +1,22 @@
import dynamic from "next/dynamic";
import { Suspense, useContext } from "react";

import { Context } from "../provider";
import { Fallback } from "./fallback";

const Component = dynamic(() => import("./component"));

// Example component that depends on Context (see ../provider/context.ts)
export function Example() {
const context = useContext(Context);
if (!context) return <Fallback />; // Render fallback when context is not available (dynamic import/async data fetching is still in progress)
// [ISSUE] Everything works fine until this line
// <Component /> (see ./component.tsx) will suspend for 5 seconds (e.g. fetch data, etc.)
// Within those 5 seconds, <Fallback /> SHOULD be rendered, but IT IS NOT, nothing is rendered
// Only after 5 seconds, <Component /> is render
return (
<Suspense fallback={<Fallback />}>
<Component />
</Suspense>
);
}
16 changes: 16 additions & 0 deletions components/provider/component.tsx
@@ -0,0 +1,16 @@
import { PropsWithChildren, useEffect, useState } from "react";
import { RecoilRoot } from "recoil";

import { Context } from "./context";

export default function Component({ children }: PropsWithChildren) {
// Provide example context after being mounted (client-side only). In real-world, some dynamic/asynchronous data fetching would be done here;
const [context, setContext] = useState<object>();
useEffect(() => setContext({}), [setContext]);
return (
<Context.Provider value={context}>
{/* Example heavy dependencies */}
<RecoilRoot>{children}</RecoilRoot>
</Context.Provider>
);
}
4 changes: 4 additions & 0 deletions components/provider/context.ts
@@ -0,0 +1,4 @@
import { createContext } from "react";

// Example context whose value will be provided dynamically/asynchronously in by Provider component (see ./index.tsx)
export const Context = createContext<object | undefined>(undefined);
15 changes: 15 additions & 0 deletions components/provider/index.tsx
@@ -0,0 +1,15 @@
import dynamic from "next/dynamic";
import { Fragment, PropsWithChildren, Suspense } from "react";

// Dynamically import the actual Provider component because it contains some heavy dependencies
const Component = dynamic(() => import("./component"));

export * from "./context";

export function Provider(props: PropsWithChildren) {
return (
<Suspense fallback={<Fragment {...props} />}>
<Component {...props} />
</Suspense>
);
}
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -14,8 +14,10 @@
"@types/react": "18.0.27",
"@types/react-dom": "18.0.10",
"next": "13.1.6",
"prettier": "^2.8.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"recoil": "^0.7.6",
"typescript": "4.9.5"
}
}
13 changes: 10 additions & 3 deletions pages/_app.tsx
@@ -1,6 +1,13 @@
import '@/styles/globals.css'
import type { AppProps } from 'next/app'
import "@/styles/globals.css";

import type { AppProps } from "next/app";

import { Provider } from "@/components/provider";

export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
return (
<Provider>
<Component {...pageProps} />
</Provider>
);
}
13 changes: 0 additions & 13 deletions pages/api/hello.ts

This file was deleted.

38 changes: 12 additions & 26 deletions pages/index.tsx
@@ -1,9 +1,11 @@
import Head from 'next/head'
import Image from 'next/image'
import { Inter } from '@next/font/google'
import styles from '@/styles/Home.module.css'
import styles from "@/styles/Home.module.css";

const inter = Inter({ subsets: ['latin'] })
import Head from "next/head";
import Image from "next/image";
import { Inter } from "@next/font/google";
import { Example } from "@/components/example";

const inter = Inter({ subsets: ["latin"] });

export default function Home() {
return (
Expand All @@ -26,7 +28,7 @@ export default function Home() {
target="_blank"
rel="noopener noreferrer"
>
By{' '}
By{" "}
<Image
src="/vercel.svg"
alt="Vercel Logo"
Expand All @@ -39,25 +41,9 @@ export default function Home() {
</div>
</div>

<div className={styles.center}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
<div className={styles.thirteen}>
<Image
src="/thirteen.svg"
alt="13"
width={40}
height={31}
priority
/>
</div>
</div>
{/* [BUG] This example component should render "Loading…" for 5 seconds then render Next.js logo but it doesn't
Instead, it renders nothing for 5 seconds then render Next.js logo. */}
<Example />

<div className={styles.grid}>
<a
Expand Down Expand Up @@ -119,5 +105,5 @@ export default function Home() {
</div>
</main>
</>
)
);
}
17 changes: 17 additions & 0 deletions yarn.lock
Expand Up @@ -130,6 +130,11 @@ csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==

hamt_plus@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hamt_plus/-/hamt_plus-1.0.2.tgz#e21c252968c7e33b20f6a1b094cd85787a265601"
integrity sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==

"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
Expand Down Expand Up @@ -186,6 +191,11 @@ postcss@8.4.14:
picocolors "^1.0.0"
source-map-js "^1.0.2"

prettier@^2.8.3:
version "2.8.3"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.3.tgz#ab697b1d3dd46fb4626fbe2f543afe0cc98d8632"
integrity sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==

react-dom@18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
Expand All @@ -201,6 +211,13 @@ react@18.2.0:
dependencies:
loose-envify "^1.1.0"

recoil@^0.7.6:
version "0.7.6"
resolved "https://registry.yarnpkg.com/recoil/-/recoil-0.7.6.tgz#75297ecd70bbfeeb72e861aa6141a86bb6dfcd5e"
integrity sha512-hsBEw7jFdpBCY/tu2GweiyaqHKxVj6EqF2/SfrglbKvJHhpN57SANWvPW+gE90i3Awi+A5gssOd3u+vWlT+g7g==
dependencies:
hamt_plus "1.0.2"

scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
Expand Down

0 comments on commit bc90ef3

Please sign in to comment.