From ed20748d8ff8ec50dd49a1d453c14f66a2ce1ec7 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 1 Dec 2022 20:16:32 +0000 Subject: [PATCH] [Beta] Rewrite Suspense API, add useDeferredValue API (#5308) * [Beta] Rewrite Suspense API * edits * more udv * edits * edit * more ref * extract * Temporary remove use --- beta/src/content/apis/react/Suspense.md | 2609 +++++++++++++++-- beta/src/content/apis/react/useDebugValue.md | 2 +- .../content/apis/react/useDeferredValue.md | 952 +++++- beta/src/sidebarAPIs.json | 11 +- 4 files changed, 3390 insertions(+), 184 deletions(-) diff --git a/beta/src/content/apis/react/Suspense.md b/beta/src/content/apis/react/Suspense.md index 69136525f..e640064c7 100644 --- a/beta/src/content/apis/react/Suspense.md +++ b/beta/src/content/apis/react/Suspense.md @@ -21,174 +21,27 @@ title: Suspense ## Usage {/*usage*/} -### Displaying a fallback while something is loading {/*displaying-a-fallback-while-something-is-loading*/} +### Displaying a fallback while content is loading {/*displaying-a-fallback-while-content-is-loading*/} -You can wrap any part of your application with a Suspense component. If either data or code in its children hasn't loaded yet, React will switch to rendering the `fallback` prop instead. For example: +You can wrap any part of your application with a Suspense boundary: -```js [[1, 3, ""], [2, 4, ""]] -<> - - }> - - - -``` - -Suppose that `Comments` takes longer to load than `Post`. Without a Suspense boundary, React wouldn't be able to show either component until both have loaded — `Post` would be blocked by `Comments`. - -Because of the Suspense boundary, `Post` doesn't need to wait for `Comments`. React renders `LoadingSpinner` in its place. Once `Comments` finishes loading, React replaces `LoadingSpinner` with `Comments`. - -Suspense will never show unintentional "holes" in your content. For example, if `PhotoAlbums` has loaded but `Notes` have not, with the structure below, it will still show a `LoadingSpinner` instead of the entire `Grid`: - -```js {4-7} -<> - - }> - - - - - - -``` - -To reveal nested content as it loads, you need to [add more Suspense boundaries.](#revealing-nested-content-as-it-loads) - - - -**Only Suspense-enabled data sources will activate a Suspense boundary.** These data sources are said to *suspend* when the data needed to render has not yet loaded. Currently, Suspense is only supported for: - -- [Lazy-loading components](#suspense-for-code-splitting) -- Data fetching with opinionated frameworks like [Relay](https://relay.dev/docs/guided-tour/rendering/loading-states/), [Next.js](https://nextjs.org/docs/advanced-features/react-18), [Hydrogen](https://hydrogen.shopify.dev/), and [Remix](https://remix.run/) - -Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React. - -Suspense does not detect when data is fetched inside an Effect or event handler. - - - ---- - -### Revealing nested content as it loads {/*revealing-nested-content-as-it-loads*/} - -When a component suspends, it activates the fallback of only the nearest parent Suspense boundary. This means you can nest multiple Suspense boundaries to create a loading sequence. Each Suspense boundary's fallback will be filled in as the next level of content becomes available. - -To illustrate, consider the following example: - -```js {1,4} -}> - - - }> - - - +```js [[1, 1, ""], [2, 2, ""]] +}> + ``` -The sequence will be: +React will display your loading fallback until all the code and data needed by the children has been loaded. -- If `Post` hasn't loaded yet, `BigSpinner` is shown in place of the entire main content area. -- Once `Post` finishes loading, `BigSpinner` is replaced by the main content. -- If `Comments` hasn't loaded yet, `CommentsGlimmer` is shown in its place. -- Finally, once `Comments` finishes loading, it replaces `CommentsGlimmer`. - ---- - -### Lazy-loading components with Suspense {/*lazy-loading-components-with-suspense*/} - -The [`lazy`](/apis/react/lazy) API is powered by Suspense. When you render a component imported with `lazy`, it will suspend if it hasn't loaded yet. This allows you to display a loading indicator while your component's code is loading. - -```js {3,12-15} -import { lazy, Suspense, useState } from 'react'; - -const MarkdownPreview = lazy(() => import('./MarkdownPreview.js')); - -function MarkdownEditor() { - const [showPreview, setShowPreview] = useState(false); - // ... - return ( - <> - ... - {showPreview && ( - }> -

Preview

- -
- )} - - ); -} -``` - -In this example, the code for `MarkdownPreview` won't be loaded until you attempt to render it. If `MarkdownPreview` hasn't loaded yet, `Loading` will be shown in its place. Try ticking the checkbox: +In the example below, the `Albums` component *suspends* while fetching the list of albums. Until it's ready to render, React switches the closest Suspense boundary above to show the fallback--your `Loading` component. Then, when the data loads, React hides the `Loading` fallback and renders the `Albums` component with data. -```js App.js -import { useState, Suspense, lazy } from 'react'; -import Loading from './Loading.js'; - -const MarkdownPreview = lazy(() => delayForDemo(import('./MarkdownPreview.js'))); - -export default function MarkdownEditor() { - const [showPreview, setShowPreview] = useState(false); - const [markdown, setMarkdown] = useState('Hello, **world**!'); - return ( - <> -