diff --git a/scripts/deadLinkChecker.js b/scripts/deadLinkChecker.js index 349231b1d..e91b46c25 100644 --- a/scripts/deadLinkChecker.js +++ b/scripts/deadLinkChecker.js @@ -12,12 +12,16 @@ const anchorMap = new Map(); // Map> const contributorMap = new Map(); // Map <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= const redirectMap = new Map(); // Map >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 ======= const redirectMap = new Map(); // Map >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +const redirectMap = new Map(); // Map +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 let errorCodes = new Set(); async function readFileWithCache(filePath) { @@ -170,11 +174,14 @@ async function validateLink(link) { return {valid: true}; } +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD ======= ======= >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 // Check for redirects if (redirectMap.has(urlWithoutAnchor)) { const redirectDestination = redirectMap.get(urlWithoutAnchor); @@ -191,10 +198,13 @@ async function validateLink(link) { return validateLink(redirectedLink); } +<<<<<<< HEAD <<<<<<< HEAD >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 ======= >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 // Check if it's an error code link const errorCodeMatch = urlWithoutAnchor.match(/^\/errors\/(\d+)$/); if (errorCodeMatch) { @@ -329,6 +339,7 @@ async function fetchErrorCodes() { const codes = await response.json(); errorCodes = new Set(Object.keys(codes)); <<<<<<< HEAD +<<<<<<< HEAD <<<<<<< HEAD console.log(chalk.gray(`Fetched ${errorCodes.size} React error codes\n`)); ======= @@ -337,16 +348,22 @@ async function fetchErrorCodes() { ======= console.log(chalk.gray(`Fetched ${errorCodes.size} React error codes`)); >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= + console.log(chalk.gray(`Fetched ${errorCodes.size} React error codes`)); +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 } catch (error) { throw new Error(`Failed to fetch error codes: ${error.message}`); } } +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD ======= ======= >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 async function buildRedirectsMap() { try { const vercelConfigPath = path.join(__dirname, '../vercel.json'); @@ -371,10 +388,13 @@ async function buildRedirectsMap() { } } +<<<<<<< HEAD <<<<<<< HEAD >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 ======= >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 async function main() { const files = getMarkdownFiles(); console.log(chalk.gray(`Checking ${files.length} markdown files...`)); @@ -382,12 +402,16 @@ async function main() { await fetchErrorCodes(); <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= await buildRedirectsMap(); >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 ======= await buildRedirectsMap(); >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= + await buildRedirectsMap(); +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 await buildContributorMap(); await buildAnchorMap(files); @@ -399,12 +423,16 @@ async function main() { if (deadLinks.length > 0) { <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= console.log('\n'); >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 ======= console.log('\n'); >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= + console.log('\n'); +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 for (const link of deadLinks) { console.log(chalk.yellow(`${link.file}:${link.line}:${link.column}`)); console.log(chalk.reset(` Link text: ${link.text}`)); diff --git a/src/components/Layout/HomeContent.js b/src/components/Layout/HomeContent.js index 59fbab80d..827e705a4 100644 --- a/src/components/Layout/HomeContent.js +++ b/src/components/Layout/HomeContent.js @@ -765,9 +765,7 @@ function CommunityGallery() { }, []); return ( -
+
- {alt} +
+ {alt} +
))} diff --git a/src/content/learn/add-react-to-an-existing-project.md b/src/content/learn/add-react-to-an-existing-project.md index f3fc43d2c..570d9b56f 100644 --- a/src/content/learn/add-react-to-an-existing-project.md +++ b/src/content/learn/add-react-to-an-existing-project.md @@ -24,6 +24,7 @@ Here's how we recommend to set it up: 2. **Specify `/some-app` as the *base path*** in your framework's configuration (here's how: [Next.js](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath), [Gatsby](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/path-prefix/)). 3. **Configure your server or a proxy** so that all requests under `/some-app/` are handled by your React app. +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD This ensures the React part of your app can [benefit from the best practices](/learn/creating-a-react-app#full-stack-frameworks) baked into those frameworks. @@ -33,6 +34,9 @@ This ensures the React part of your app can [benefit from the best practices](/l ======= This ensures the React part of your app can [benefit from the best practices](/learn/build-a-react-app-from-scratch#consider-using-a-framework) baked into those frameworks. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +This ensures the React part of your app can [benefit from the best practices](/learn/build-a-react-app-from-scratch#consider-using-a-framework) baked into those frameworks. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 Many React-based frameworks are full-stack and let your React app take advantage of the server. However, you can use the same approach even if you can't or don't want to run JavaScript on the server. In that case, serve the HTML/CSS/JS export ([`next export` output](https://nextjs.org/docs/advanced-features/static-html-export) for Next.js, default for Gatsby) at `/some-app/` instead. diff --git a/src/content/learn/synchronizing-with-effects.md b/src/content/learn/synchronizing-with-effects.md index 633fd04f9..e025cdc7a 100644 --- a/src/content/learn/synchronizing-with-effects.md +++ b/src/content/learn/synchronizing-with-effects.md @@ -732,6 +732,7 @@ Writing `fetch` calls inside Effects is a [popular way to fetch data](https://ww This list of downsides is not specific to React. It applies to fetching data on mount with any library. Like with routing, data fetching is not trivial to do well, so we recommend the following approaches: +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD - **If you use a [framework](/learn/creating-a-react-app#full-stack-frameworks), use its built-in data fetching mechanism.** Modern React frameworks have integrated data fetching mechanisms that are efficient and don't suffer from the above pitfalls. @@ -741,6 +742,9 @@ This list of downsides is not specific to React. It applies to fetching data on ======= - **If you use a [framework](/learn/start-a-new-react-project#full-stack-frameworks), use its built-in data fetching mechanism.** Modern React frameworks have integrated data fetching mechanisms that are efficient and don't suffer from the above pitfalls. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +- **If you use a [framework](/learn/start-a-new-react-project#full-stack-frameworks), use its built-in data fetching mechanism.** Modern React frameworks have integrated data fetching mechanisms that are efficient and don't suffer from the above pitfalls. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 - **Otherwise, consider using or building a client-side cache.** Popular open source solutions include [React Query](https://tanstack.com/query/latest), [useSWR](https://swr.vercel.app/), and [React Router 6.4+.](https://beta.reactrouter.com/en/main/start/overview) You can build your own solution too, in which case you would use Effects under the hood, but add logic for deduplicating requests, caching responses, and avoiding network waterfalls (by preloading data or hoisting data requirements to routes). You can continue fetching data directly in Effects if neither of these approaches suit you. diff --git a/src/content/learn/typescript.md b/src/content/learn/typescript.md index 58bca60e9..66357f2e2 100644 --- a/src/content/learn/typescript.md +++ b/src/content/learn/typescript.md @@ -20,6 +20,7 @@ TypeScript is a popular way to add type definitions to JavaScript codebases. Out ## Installation {/*installation*/} +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD All [production-grade React frameworks](/learn/creating-a-react-app#full-stack-frameworks) offer support for using TypeScript. Follow the framework specific guide for installation: @@ -29,6 +30,9 @@ All [production-grade React frameworks](/learn/start-a-new-react-project#full-st ======= All [production-grade React frameworks](/learn/start-a-new-react-project#full-stack-frameworks) offer support for using TypeScript. Follow the framework specific guide for installation: >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +All [production-grade React frameworks](/learn/start-a-new-react-project#full-stack-frameworks) offer support for using TypeScript. Follow the framework specific guide for installation: +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 - [Next.js](https://nextjs.org/docs/app/building-your-application/configuring/typescript) - [Remix](https://remix.run/docs/en/1.19.2/guides/typescript) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index a683be1f4..ce4f6ed22 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -26,6 +26,7 @@ There are two common cases in which you don't need Effects: * **You don't need Effects to transform data for rendering.** For example, let's say you want to filter a list before displaying it. You might feel tempted to write an Effect that updates a state variable when the list changes. However, this is inefficient. When you update the state, React will first call your component functions to calculate what should be on the screen. Then React will ["commit"](/learn/render-and-commit) these changes to the DOM, updating the screen. Then React will run your Effects. If your Effect *also* immediately updates the state, this restarts the whole process from scratch! To avoid the unnecessary render passes, transform all the data at the top level of your components. That code will automatically re-run whenever your props or state change. * **You don't need Effects to handle user events.** For example, let's say you want to send an `/api/buy` POST request and show a notification when the user buys a product. In the Buy button click event handler, you know exactly what happened. By the time an Effect runs, you don't know *what* the user did (for example, which button was clicked). This is why you'll usually handle user events in the corresponding event handlers. +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD You *do* need Effects to [synchronize](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) with external systems. For example, you can write an Effect that keeps a jQuery widget synchronized with the React state. You can also fetch data with Effects: for example, you can synchronize the search results with the current search query. Keep in mind that modern [frameworks](/learn/creating-a-react-app#full-stack-frameworks) provide more efficient built-in data fetching mechanisms than writing Effects directly in your components. @@ -35,6 +36,9 @@ You *do* need Effects to [synchronize](/learn/synchronizing-with-effects#what-ar ======= You *do* need Effects to [synchronize](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) with external systems. For example, you can write an Effect that keeps a jQuery widget synchronized with the React state. You can also fetch data with Effects: for example, you can synchronize the search results with the current search query. Keep in mind that modern [frameworks](/learn/start-a-new-react-project#full-stack-frameworks) provide more efficient built-in data fetching mechanisms than writing Effects directly in your components. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +You *do* need Effects to [synchronize](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) with external systems. For example, you can write an Effect that keeps a jQuery widget synchronized with the React state. You can also fetch data with Effects: for example, you can synchronize the search results with the current search query. Keep in mind that modern [frameworks](/learn/start-a-new-react-project#full-stack-frameworks) provide more efficient built-in data fetching mechanisms than writing Effects directly in your components. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 To help you gain the right intuition, let's look at some common concrete examples! @@ -765,6 +769,7 @@ This ensures that when your Effect fetches data, all responses except the last r Handling race conditions is not the only difficulty with implementing data fetching. You might also want to think about caching responses (so that the user can click Back and see the previous screen instantly), how to fetch data on the server (so that the initial server-rendered HTML contains the fetched content instead of a spinner), and how to avoid network waterfalls (so that a child can fetch data without waiting for every parent). +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD **These issues apply to any UI library, not just React. Solving them is not trivial, which is why modern [frameworks](/learn/creating-a-react-app#full-stack-frameworks) provide more efficient built-in data fetching mechanisms than fetching data in Effects.** @@ -774,6 +779,9 @@ Handling race conditions is not the only difficulty with implementing data fetch ======= **These issues apply to any UI library, not just React. Solving them is not trivial, which is why modern [frameworks](/learn/start-a-new-react-project#full-stack-frameworks) provide more efficient built-in data fetching mechanisms than fetching data in Effects.** >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +**These issues apply to any UI library, not just React. Solving them is not trivial, which is why modern [frameworks](/learn/start-a-new-react-project#full-stack-frameworks) provide more efficient built-in data fetching mechanisms than fetching data in Effects.** +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 If you don't use a framework (and don't want to build your own) but would like to make data fetching from Effects more ergonomic, consider extracting your fetching logic into a custom Hook like in this example: diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index 7097f65e7..148d0d175 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -209,6 +209,7 @@ When your HTML is empty, the user sees a blank page until the app's JavaScript c
``` +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD This can feel very slow! To solve this, you can generate the initial HTML from your components [on the server or during the build.](/reference/react-dom/server) Then your visitors can read text, see images, and click links before any of the JavaScript code loads. We recommend [using a framework](/learn/creating-a-react-app#full-stack-frameworks) that does this optimization out of the box. Depending on when it runs, this is called *server-side rendering (SSR)* or *static site generation (SSG).* @@ -218,6 +219,9 @@ This can feel very slow! To solve this, you can generate the initial HTML from y ======= This can feel very slow! To solve this, you can generate the initial HTML from your components [on the server or during the build.](/reference/react-dom/server) Then your visitors can read text, see images, and click links before any of the JavaScript code loads. We recommend [using a framework](/learn/start-a-new-react-project#full-stack-frameworks) that does this optimization out of the box. Depending on when it runs, this is called *server-side rendering (SSR)* or *static site generation (SSG).* >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +This can feel very slow! To solve this, you can generate the initial HTML from your components [on the server or during the build.](/reference/react-dom/server) Then your visitors can read text, see images, and click links before any of the JavaScript code loads. We recommend [using a framework](/learn/start-a-new-react-project#full-stack-frameworks) that does this optimization out of the box. Depending on when it runs, this is called *server-side rendering (SSR)* or *static site generation (SSG).* +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 diff --git a/src/content/reference/react-dom/client/index.md b/src/content/reference/react-dom/client/index.md index d76d33d5f..b599931d8 100644 --- a/src/content/reference/react-dom/client/index.md +++ b/src/content/reference/react-dom/client/index.md @@ -4,6 +4,7 @@ title: Client React DOM APIs +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD The `react-dom/client` APIs let you render React components on the client (in the browser). These APIs are typically used at the top level of your app to initialize your React tree. A [framework](/learn/creating-a-react-app#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. @@ -13,6 +14,9 @@ The `react-dom/client` APIs let you render React components on the client (in th ======= The `react-dom/client` APIs let you render React components on the client (in the browser). These APIs are typically used at the top level of your app to initialize your React tree. A [framework](/learn/start-a-new-react-project#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +The `react-dom/client` APIs let you render React components on the client (in the browser). These APIs are typically used at the top level of your app to initialize your React tree. A [framework](/learn/start-a-new-react-project#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 diff --git a/src/content/reference/react-dom/server/index.md b/src/content/reference/react-dom/server/index.md index a465d551f..2e4f8022a 100644 --- a/src/content/reference/react-dom/server/index.md +++ b/src/content/reference/react-dom/server/index.md @@ -4,6 +4,7 @@ title: Server React DOM APIs +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD The `react-dom/server` APIs let you server-side render React components to HTML. These APIs are only used on the server at the top level of your app to generate the initial HTML. A [framework](/learn/creating-a-react-app#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. @@ -13,6 +14,9 @@ The `react-dom/server` APIs let you server-side render React components to HTML. ======= The `react-dom/server` APIs let you server-side render React components to HTML. These APIs are only used on the server at the top level of your app to generate the initial HTML. A [framework](/learn/start-a-new-react-project#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +The `react-dom/server` APIs let you server-side render React components to HTML. These APIs are only used on the server at the top level of your app to generate the initial HTML. A [framework](/learn/start-a-new-react-project#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 diff --git a/src/content/reference/react-dom/static/index.md b/src/content/reference/react-dom/static/index.md index 011adc083..6c9e5ef78 100644 --- a/src/content/reference/react-dom/static/index.md +++ b/src/content/reference/react-dom/static/index.md @@ -4,6 +4,7 @@ title: Static React DOM APIs +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD The `react-dom/static` APIs let you generate static HTML for React components. They have limited functionality compared to the streaming APIs. A [framework](/learn/creating-a-react-app#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. @@ -13,6 +14,9 @@ The `react-dom/static` APIs let you generate static HTML for React components. T ======= The `react-dom/static` APIs let you generate static HTML for React components. They have limited functionality compared to the streaming APIs. A [framework](/learn/start-a-new-react-project#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +The `react-dom/static` APIs let you generate static HTML for React components. They have limited functionality compared to the streaming APIs. A [framework](/learn/start-a-new-react-project#full-stack-frameworks) may call them for you. Most of your components don't need to import or use them. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 diff --git a/src/content/reference/react-dom/static/prerender.md b/src/content/reference/react-dom/static/prerender.md index a47caffc8..365149293 100644 --- a/src/content/reference/react-dom/static/prerender.md +++ b/src/content/reference/react-dom/static/prerender.md @@ -76,6 +76,7 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to <<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD `nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the a nonce value in the prerender itself. ======= `nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself. @@ -101,6 +102,9 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to ======= `nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +`nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 diff --git a/src/content/reference/react-dom/static/prerenderToNodeStream.md b/src/content/reference/react-dom/static/prerenderToNodeStream.md index 126e29a3b..893b1434f 100644 --- a/src/content/reference/react-dom/static/prerenderToNodeStream.md +++ b/src/content/reference/react-dom/static/prerenderToNodeStream.md @@ -77,6 +77,7 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to <<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD `nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the a nonce value in the prerender itself. ======= `nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself. @@ -102,6 +103,9 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to ======= `nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself. >>>>>>> e07ac94bc2c1ffd817b13930977be93325e5bea9 +======= +`nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself. +>>>>>>> e9a7cb1b6ca1659b42d81555ecef0cd554b7a983 diff --git a/src/content/reference/react/Activity.md b/src/content/reference/react/Activity.md index 8b103938e..f437a74da 100644 --- a/src/content/reference/react/Activity.md +++ b/src/content/reference/react/Activity.md @@ -19,12 +19,11 @@ Experimental versions of React may contain bugs. Don't use them in production. -`` lets you hide and show part of the UI. - +`` lets you hide and restore the UI and internal state of its children. ```js - - + + ``` @@ -38,223 +37,270 @@ Experimental versions of React may contain bugs. Don't use them in production. ### `` {/*activity*/} -Wrap a part of the UI in `` to manage its visibility state: - -```js -import {unstable_Activity as Activity} from 'react'; +You can use Activity to hide part of your application: - - +```js [[1, 1, "\\"hidden\\""], [2, 2, ""], [3, 1, "\\"visible\\""]] + + ``` -When "hidden", the `children` of `` are not visible on the page. If a new `` mounts as "hidden" then it pre-renders the content at lower priority without blocking the visible content on the page, but it does not mount by creating Effects. When a "visible" Activity switches to "hidden" it conceptually unmounts by destroying all the Effects, but saves its state. This allows fast switching between "visible" and "hidden" states without recreating the state for a "hidden" Activity. +When an Activity boundary is hidden, React will visually hide its children using the `display: "none"` CSS property. It will also destroy their Effects, cleaning up any active subscriptions. + +While hidden, children still re-render in response to new props, albeit at a lower priority than the rest of the content. -In the future, "hidden" Activities may automatically destroy state based on resources like memory. +When the boundary becomes visible again, React will reveal the children with their previous state restored, and re-create their Effects. + +In this way, Activity can thought of as a mechanism for rendering "background activity". Rather than completely discarding content that's likely to become visible again, you can use Activity to maintain and restore that content's UI and internal state, while ensuring hidden content has no unwanted side effects. + +[See more examples below.](#usage) #### Props {/*props*/} -* `children`: The actual UI you intend to render. -* **optional** `mode`: Either "visible" or "hidden". Defaults to "visible". When "hidden", updates to the children are deferred to lower priority. The component will not create Effects until the Activity is switched to "visible". If a "visible" Activity switches to "hidden", the Effects will be destroyed. +* `children`: The UI you intend to show and hide. +* `mode`: A string value of either `'visible'` or `'hidden'`. If omitted, defaults to `'visible'`. #### Caveats {/*caveats*/} -- While hidden, the `children` of `` are hidden on the page. -- `` will unmount all Effects when switching from "visible" to "hidden" without destroying React or DOM state. This means Effects that are expected to run only once on mount will run again when switching from "hidden" to "visible". Conceptually, "hidden" Activities are unmounted, but they are not destroyed either. We recommend using [``](/reference/react/StrictMode) to catch any unexpected side-effects from this behavior. - When used with ``, hidden activities that reveal in a transition will activate an "enter" animation. Visible Activities hidden in a transition will activate an "exit" animation. -- Parts of the UI wrapped in `` are not included in the SSR response. -- Parts of the UI wrapped in `` will hydrate at a lower priority than other content. --- ## Usage {/*usage*/} -### Pre-render part of the UI {/*pre-render-part-of-the-ui*/} +### Restoring the state of hidden components {/*restoring-the-state-of-hidden-components*/} -You can pre-render part of the UI using ``: +Typically in React, when you want to conditionally show or hide a component, you mount and unmount it: -```js - - +```jsx +{isShowingSidebar && ( + +)} +``` + +But unmounting a component destroys its internal state, which is not always what you want. + +When you hide a component using an Activity boundary instead, React will "save" its state for later: + +```jsx + + ``` -When an Activity is rendered with `mode="hidden"`, the `children` are not visible on the page, but are rendered at lower priority than the visible content on the page. +This makes it possible to restore components to their previous state. -When the `mode` later switches to "visible", the pre-rendered children will mount and become visible. This can be used to prepare parts of the UI the user is likely to interact with next to reduce loading times. +The following example has a sidebar with an expandable section – you can press "Overview" to reveal the three subitems below it. The main app area also has a button that hides and shows the sidebar. -In the following example from [`useTransition`](/reference/react/useTransition#preventing-unwanted-loading-indicators), the `PostsTab` component fetches some data using `use`. When you click the β€œPosts” tab, the `PostsTab` component suspends, causing the button loading state to appear: +Try expanding the Overview section, then toggling the sidebar closed and open: -```js -import { Suspense, useState } from 'react'; -import TabButton from './TabButton.js'; -import AboutTab from './AboutTab.js'; -import PostsTab from './PostsTab.js'; -import ContactTab from './ContactTab.js'; +```js src/App.js active +import { useState } from 'react'; +import Sidebar from './Sidebar.js'; + +export default function App() { + const [isShowingSidebar, setIsShowingSidebar] = useState(true); -export default function TabContainer() { - const [tab, setTab] = useState('about'); return ( - πŸŒ€ Loading...}> - setTab('about')} - > - About - - setTab('posts')} - > - Posts - - setTab('contact')} - > - Contact - -
- {tab === 'about' && } - {tab === 'posts' && } - {tab === 'contact' && } -
+ <> + {isShowingSidebar && ( + + )} + +
+ +

Main content

+
+ ); } ``` +```js src/Sidebar.js +import { useState } from 'react'; -```js src/TabButton.js active -import { useTransition } from 'react'; - -export default function TabButton({ action, children, isActive }) { - const [isPending, startTransition] = useTransition(); - if (isActive) { - return {children} - } - if (isPending) { - return {children}; - } +export default function Sidebar() { + const [isExpanded, setIsExpanded] = useState(false) + return ( - + ); } ``` -```js src/AboutTab.js hidden -import {unstable_ViewTransition as ViewTransition} from 'react'; +```css +body { height: 275px; margin: 0; } +#root { + display: flex; + gap: 10px; + height: 100%; +} +nav { + padding: 10px; + background: #eee; + font-size: 14px; + height: 100%; +} +main { + padding: 10px; +} +p { + margin: 0; +} +h1 { + margin-top: 10px; +} +.indicator { + margin-left: 4px; + display: inline-block; + rotate: 90deg; +} +.indicator.down { + rotate: 180deg; +} +``` -export default function AboutTab() { - return ( - -

Welcome to my profile!

-
- ); +```json package.json hidden +{ + "dependencies": { + "react": "experimental", + "react-dom": "experimental", + "react-scripts": "latest", + "toastify-js": "1.12.0" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + } } ``` -```js src/PostsTab.js hidden -import {use, unstable_ViewTransition as ViewTransition} from 'react'; -import { fetchData } from './data.js'; +
-function PostsTab() { - const posts = use(fetchData('/posts')); - return ( - -
    - {posts.map(post => - - )} -
-
- ); -} +The Overview section always starts out collapsed. Because we unmount the sidebar when `isShowingSidebar` flips to `false`, all its internal state is lost. -function Post({ title }) { - return ( -
  • - {title} -
  • - ); -} +This is a perfect use case for Activity. We can preserve the internal state of our sidebar, even when visually hiding it. -export default PostsTab; -``` +Let's replace the conditional rendering of our sidebar with an Activity boundary: -```js src/ContactTab.js hidden -import {unstable_ViewTransition as ViewTransition} from 'react'; +```jsx {7,9} +// Before +{isShowingSidebar && ( + +)} -export default function ContactTab() { - return ( - -

    - Send me a message! -

    -