From d661678b86fd906689a836385736e80bb82a4ade Mon Sep 17 00:00:00 2001 From: lauren Date: Mon, 25 Mar 2024 13:44:51 -0400 Subject: [PATCH 1/9] Update @eps1lon's job title (#6710) Congrats! https://twitter.com/sebsilbermann/status/1772229730747490691 --- src/content/community/team.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/community/team.md b/src/content/community/team.md index 2ea4e79b..bb28fe88 100644 --- a/src/content/community/team.md +++ b/src/content/community/team.md @@ -74,7 +74,7 @@ Current members of the React team are listed in alphabetical order below. Sebastian majored in psychology. He's usually quiet. Even when he says something, it often doesn't make sense to the rest of us until a few months later. The correct way to pronounce his surname is "mark-boa-geh" but he settled for "mark-beige" out of pragmatism -- and that's how he approaches React. - + Sebastian learned programming to make the browser games he played during class more enjoyable. Eventually this lead to contributing to as much open source code as possible. Outside of coding he's busy making sure people don't confuse him with the other Sebastians and Zilberman of the React community. From 4df3124fa2116cdb228caa0f1f05a3449b53bd09 Mon Sep 17 00:00:00 2001 From: Ricky Date: Tue, 26 Mar 2024 23:39:39 -0400 Subject: [PATCH 2/9] Fix caps for React concepts (#6712) --- CONTRIBUTING.md | 1 + .../learn/manipulating-the-dom-with-refs.md | 2 +- src/content/reference/react-dom/flushSync.md | 2 +- src/content/reference/react-dom/hydrate.md | 2 +- src/content/reference/react-dom/preconnect.md | 2 +- .../reference/react-dom/prefetchDNS.md | 2 +- src/content/reference/react-dom/preinit.md | 2 +- .../reference/react-dom/preinitModule.md | 2 +- src/content/reference/react-dom/preload.md | 2 +- .../reference/react-dom/preloadModule.md | 2 +- src/content/reference/react/Profiler.md | 2 +- src/content/reference/react/Suspense.md | 20 ++--- .../reference/react/startTransition.md | 24 +++--- src/content/reference/react/use-server.md | 4 +- .../reference/react/useInsertionEffect.md | 8 +- .../reference/react/useSyncExternalStore.md | 4 +- src/content/reference/react/useTransition.md | 84 +++++++++---------- .../components-and-hooks-must-be-pure.md | 12 +-- .../rules/react-calls-components-and-hooks.md | 34 ++++---- src/content/reference/rules/rules-of-hooks.md | 2 +- 20 files changed, 107 insertions(+), 106 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e861af3..4c7e5ec7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,6 +79,7 @@ Ignore this rule if you're specifically describing an experimental proposal. Mak - Use semicolons. - No space between function names and parens (`method() {}` not `method () {}`). - When in doubt, use the default style favored by [Prettier](https://prettier.io/playground/). +- Always capitalize React concepts such as Hooks, Effects, and Transitions. ### Highlighting diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index 3d5cbfd1..bc9a3eac 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -493,7 +493,7 @@ In general, you [don't want](/learn/referencing-values-with-refs#best-practices- React sets `ref.current` during the commit. Before updating the DOM, React sets the affected `ref.current` values to `null`. After updating the DOM, React immediately sets them to the corresponding DOM nodes. -**Usually, you will access refs from event handlers.** If you want to do something with a ref, but there is no particular event to do it in, you might need an Effect. We will discuss effects on the next pages. +**Usually, you will access refs from event handlers.** If you want to do something with a ref, but there is no particular event to do it in, you might need an Effect. We will discuss Effects on the next pages. diff --git a/src/content/reference/react-dom/flushSync.md b/src/content/reference/react-dom/flushSync.md index a97d194e..e23ef4ea 100644 --- a/src/content/reference/react-dom/flushSync.md +++ b/src/content/reference/react-dom/flushSync.md @@ -53,7 +53,7 @@ Most of the time, `flushSync` can be avoided. Use `flushSync` as last resort. * `flushSync` can significantly hurt performance. Use sparingly. * `flushSync` may force pending Suspense boundaries to show their `fallback` state. -* `flushSync` may run pending effects and synchronously apply any updates they contain before returning. +* `flushSync` may run pending Effects and synchronously apply any updates they contain before returning. * `flushSync` may flush updates outside the callback when necessary to flush the updates inside the callback. For example, if there are pending updates from a click, React may flush those before flushing the updates inside the callback. --- diff --git a/src/content/reference/react-dom/hydrate.md b/src/content/reference/react-dom/hydrate.md index 0d1e1cdf..a005abf1 100644 --- a/src/content/reference/react-dom/hydrate.md +++ b/src/content/reference/react-dom/hydrate.md @@ -152,7 +152,7 @@ This only works one level deep, and is intended to be an escape hatch. Don’t o ### Handling different client and server content {/*handling-different-client-and-server-content*/} -If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a [state variable](/reference/react/useState) like `isClient`, which you can set to `true` in an [effect](/reference/react/useEffect): +If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a [state variable](/reference/react/useState) like `isClient`, which you can set to `true` in an [Effect](/reference/react/useEffect): diff --git a/src/content/reference/react-dom/preconnect.md b/src/content/reference/react-dom/preconnect.md index cb14a5e8..9b3100b0 100644 --- a/src/content/reference/react-dom/preconnect.md +++ b/src/content/reference/react-dom/preconnect.md @@ -55,7 +55,7 @@ The `preconnect` function provides the browser with a hint that it should open a #### Caveats {/*caveats*/} * Multiple calls to `preconnect` with the same server have the same effect as a single call. -* In the browser, you can call `preconnect` in any situation: while rendering a component, in an effect, in an event handler, and so on. +* In the browser, you can call `preconnect` in any situation: while rendering a component, in an Effect, in an event handler, and so on. * In server-side rendering or when rendering Server Components, `preconnect` only has an effect if you call it while rendering a component or in an async context originating from rendering a component. Any other calls will be ignored. * If you know the specific resources you'll need, you can call [other functions](/reference/react-dom/#resource-preloading-apis) instead that will start loading the resources right away. * There is no benefit to preconnecting to the same server the webpage itself is hosted from because it's already been connected to by the time the hint would be given. diff --git a/src/content/reference/react-dom/prefetchDNS.md b/src/content/reference/react-dom/prefetchDNS.md index f9889836..fc9ffdb1 100644 --- a/src/content/reference/react-dom/prefetchDNS.md +++ b/src/content/reference/react-dom/prefetchDNS.md @@ -54,7 +54,7 @@ The prefetchDNS function provides the browser with a hint that it should look up #### Caveats {/*caveats*/} * Multiple calls to `prefetchDNS` with the same server have the same effect as a single call. -* In the browser, you can call `prefetchDNS` in any situation: while rendering a component, in an effect, in an event handler, and so on. +* In the browser, you can call `prefetchDNS` in any situation: while rendering a component, in an Effect, in an event handler, and so on. * In server-side rendering or when rendering Server Components, `prefetchDNS` only has an effect if you call it while rendering a component or in an async context originating from rendering a component. Any other calls will be ignored. * If you know the specific resources you'll need, you can call [other functions](/reference/react-dom/#resource-preloading-apis) instead that will start loading the resources right away. * There is no benefit to prefetching the same server the webpage itself is hosted from because it's already been looked up by the time the hint would be given. diff --git a/src/content/reference/react-dom/preinit.md b/src/content/reference/react-dom/preinit.md index 5a04528b..3c9a879b 100644 --- a/src/content/reference/react-dom/preinit.md +++ b/src/content/reference/react-dom/preinit.md @@ -67,7 +67,7 @@ The `preinit` function provides the browser with a hint that it should start dow #### Caveats {/*caveats*/} * Multiple calls to `preinit` with the same `href` have the same effect as a single call. -* In the browser, you can call `preinit` in any situation: while rendering a component, in an effect, in an event handler, and so on. +* In the browser, you can call `preinit` in any situation: while rendering a component, in an Effect, in an event handler, and so on. * In server-side rendering or when rendering Server Components, `preinit` only has an effect if you call it while rendering a component or in an async context originating from rendering a component. Any other calls will be ignored. --- diff --git a/src/content/reference/react-dom/preinitModule.md b/src/content/reference/react-dom/preinitModule.md index ba6316a7..996c5a2e 100644 --- a/src/content/reference/react-dom/preinitModule.md +++ b/src/content/reference/react-dom/preinitModule.md @@ -65,7 +65,7 @@ The `preinitModule` function provides the browser with a hint that it should sta #### Caveats {/*caveats*/} * Multiple calls to `preinitModule` with the same `href` have the same effect as a single call. -* In the browser, you can call `preinitModule` in any situation: while rendering a component, in an effect, in an event handler, and so on. +* In the browser, you can call `preinitModule` in any situation: while rendering a component, in an Effect, in an event handler, and so on. * In server-side rendering or when rendering Server Components, `preinitModule` only has an effect if you call it while rendering a component or in an async context originating from rendering a component. Any other calls will be ignored. --- diff --git a/src/content/reference/react-dom/preload.md b/src/content/reference/react-dom/preload.md index 0ad9668d..1e7fd195 100644 --- a/src/content/reference/react-dom/preload.md +++ b/src/content/reference/react-dom/preload.md @@ -72,7 +72,7 @@ The `preload` function provides the browser with a hint that it should start dow * Multiple equivalent calls to `preload` have the same effect as a single call. Calls to `preload` are considered equivalent according to the following rules: * Two calls are equivalent if they have the same `href`, except: * If `as` is set to `image`, two calls are equivalent if they have the same `href`, `imageSrcSet`, and `imageSizes`. -* In the browser, you can call `preload` in any situation: while rendering a component, in an effect, in an event handler, and so on. +* In the browser, you can call `preload` in any situation: while rendering a component, in an Effect, in an event handler, and so on. * In server-side rendering or when rendering Server Components, `preload` only has an effect if you call it while rendering a component or in an async context originating from rendering a component. Any other calls will be ignored. --- diff --git a/src/content/reference/react-dom/preloadModule.md b/src/content/reference/react-dom/preloadModule.md index 05333f1c..99d128c7 100644 --- a/src/content/reference/react-dom/preloadModule.md +++ b/src/content/reference/react-dom/preloadModule.md @@ -66,7 +66,7 @@ The `preloadModule` function provides the browser with a hint that it should sta #### Caveats {/*caveats*/} * Multiple calls to `preloadModule` with the same `href` have the same effect as a single call. -* In the browser, you can call `preloadModule` in any situation: while rendering a component, in an effect, in an event handler, and so on. +* In the browser, you can call `preloadModule` in any situation: while rendering a component, in an Effect, in an event handler, and so on. * In server-side rendering or when rendering Server Components, `preloadModule` only has an effect if you call it while rendering a component or in an async context originating from rendering a component. Any other calls will be ignored. --- diff --git a/src/content/reference/react/Profiler.md b/src/content/reference/react/Profiler.md index 502ab0d4..188b2d1b 100644 --- a/src/content/reference/react/Profiler.md +++ b/src/content/reference/react/Profiler.md @@ -54,7 +54,7 @@ function onRender(id, phase, actualDuration, baseDuration, startTime, commitTime #### Parameters {/*onrender-parameters*/} * `id`: The string `id` prop of the `` tree that has just committed. This lets you identify which part of the tree was committed if you are using multiple profilers. -* `phase`: `"mount"`, `"update"` or `"nested-update"`. This lets you know whether the tree has just been mounted for the first time or re-rendered due to a change in props, state, or hooks. +* `phase`: `"mount"`, `"update"` or `"nested-update"`. This lets you know whether the tree has just been mounted for the first time or re-rendered due to a change in props, state, or Hooks. * `actualDuration`: The number of milliseconds spent rendering the `` and its descendants for the current update. This indicates how well the subtree makes use of memoization (e.g. [`memo`](/reference/react/memo) and [`useMemo`](/reference/react/useMemo)). Ideally this value should decrease significantly after the initial mount as many of the descendants will only need to re-render if their specific props change. * `baseDuration`: The number of milliseconds estimating how much time it would take to re-render the entire `` subtree without any optimizations. It is calculated by summing up the most recent render durations of each component in the tree. This value estimates a worst-case cost of rendering (e.g. the initial mount or a tree with no memoization). Compare `actualDuration` against it to see if memoization is working. * `startTime`: A numeric timestamp for when React began rendering the current update. diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index 4ec3dd7a..abb77a9d 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -1348,7 +1348,7 @@ input { margin: 10px; } -Both deferred values and [transitions](#preventing-already-revealed-content-from-hiding) let you avoid showing Suspense fallback in favor of inline indicators. Transitions mark the whole update as non-urgent so they are typically used by frameworks and router libraries for navigation. Deferred values, on the other hand, are mostly useful in application code where you want to mark a part of UI as non-urgent and let it "lag behind" the rest of the UI. +Both deferred values and [Transitions](#preventing-already-revealed-content-from-hiding) let you avoid showing Suspense fallback in favor of inline indicators. Transitions mark the whole update as non-urgent so they are typically used by frameworks and router libraries for navigation. Deferred values, on the other hand, are mostly useful in application code where you want to mark a part of UI as non-urgent and let it "lag behind" the rest of the UI. @@ -1727,7 +1727,7 @@ main { When you pressed the button, the `Router` component rendered `ArtistPage` instead of `IndexPage`. A component inside `ArtistPage` suspended, so the closest Suspense boundary started showing the fallback. The closest Suspense boundary was near the root, so the whole site layout got replaced by `BigSpinner`. -To prevent this, you can mark the navigation state update as a *transition* with [`startTransition`:](/reference/react/startTransition) +To prevent this, you can mark the navigation state update as a *Transition* with [`startTransition`:](/reference/react/startTransition) ```js {5,7} function Router() { @@ -1741,7 +1741,7 @@ function Router() { // ... ``` -This tells React that the state transition is not urgent, and it's better to keep showing the previous page instead of hiding any already revealed content. Now clicking the button "waits" for the `Biography` to load: +This tells React that the state Transition is not urgent, and it's better to keep showing the previous page instead of hiding any already revealed content. Now clicking the button "waits" for the `Biography` to load: @@ -2112,19 +2112,19 @@ main { -A transition doesn't wait for *all* content to load. It only waits long enough to avoid hiding already revealed content. For example, the website `Layout` was already revealed, so it would be bad to hide it behind a loading spinner. However, the nested `Suspense` boundary around `Albums` is new, so the transition doesn't wait for it. +A Transition doesn't wait for *all* content to load. It only waits long enough to avoid hiding already revealed content. For example, the website `Layout` was already revealed, so it would be bad to hide it behind a loading spinner. However, the nested `Suspense` boundary around `Albums` is new, so the Transition doesn't wait for it. -Suspense-enabled routers are expected to wrap the navigation updates into transitions by default. +Suspense-enabled routers are expected to wrap the navigation updates into Transitions by default. --- -### Indicating that a transition is happening {/*indicating-that-a-transition-is-happening*/} +### Indicating that a Transition is happening {/*indicating-that-a-transition-is-happening*/} -In the above example, once you click the button, there is no visual indication that a navigation is in progress. To add an indicator, you can replace [`startTransition`](/reference/react/startTransition) with [`useTransition`](/reference/react/useTransition) which gives you a boolean `isPending` value. In the example below, it's used to change the website header styling while a transition is happening: +In the above example, once you click the button, there is no visual indication that a navigation is in progress. To add an indicator, you can replace [`startTransition`](/reference/react/startTransition) with [`useTransition`](/reference/react/useTransition) which gives you a boolean `isPending` value. In the example below, it's used to change the website header styling while a Transition is happening: @@ -2502,13 +2502,13 @@ main { ### Resetting Suspense boundaries on navigation {/*resetting-suspense-boundaries-on-navigation*/} -During a transition, React will avoid hiding already revealed content. However, if you navigate to a route with different parameters, you might want to tell React it is *different* content. You can express this with a `key`: +During a Transition, React will avoid hiding already revealed content. However, if you navigate to a route with different parameters, you might want to tell React it is *different* content. You can express this with a `key`: ```js ``` -Imagine you're navigating within a user's profile page, and something suspends. If that update is wrapped in a transition, it will not trigger the fallback for already visible content. That's the expected behavior. +Imagine you're navigating within a user's profile page, and something suspends. If that update is wrapped in a Transition, it will not trigger the fallback for already visible content. That's the expected behavior. However, now imagine you're navigating between two different user profiles. In that case, it makes sense to show the fallback. For example, one user's timeline is *different content* from another user's timeline. By specifying a `key`, you ensure that React treats different users' profiles as different components, and resets the Suspense boundaries during navigation. Suspense-integrated routers should do this automatically. @@ -2545,7 +2545,7 @@ The server HTML will include the loading indicator. It will be replaced by the ` Replacing visible UI with a fallback creates a jarring user experience. This can happen when an update causes a component to suspend, and the nearest Suspense boundary is already showing content to the user. -To prevent this from happening, [mark the update as non-urgent using `startTransition`](#preventing-already-revealed-content-from-hiding). During a transition, React will wait until enough data has loaded to prevent an unwanted fallback from appearing: +To prevent this from happening, [mark the update as non-urgent using `startTransition`](#preventing-already-revealed-content-from-hiding). During a Transition, React will wait until enough data has loaded to prevent an unwanted fallback from appearing: ```js {2-3,5} function handleNextPageClick() { diff --git a/src/content/reference/react/startTransition.md b/src/content/reference/react/startTransition.md index 0aef23fd..3b1defd2 100644 --- a/src/content/reference/react/startTransition.md +++ b/src/content/reference/react/startTransition.md @@ -20,7 +20,7 @@ startTransition(scope) ### `startTransition(scope)` {/*starttransitionscope*/} -The `startTransition` function lets you mark a state update as a transition. +The `startTransition` function lets you mark a state update as a Transition. ```js {7,9} import { startTransition } from 'react'; @@ -41,7 +41,7 @@ function TabContainer() { #### Parameters {/*parameters*/} -* `scope`: A function that updates some state by calling one or more [`set` functions.](/reference/react/useState#setstate) React immediately calls `scope` with no arguments and marks all state updates scheduled synchronously during the `scope` function call as transitions. They will be [non-blocking](/reference/react/useTransition#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](/reference/react/useTransition#preventing-unwanted-loading-indicators) +* `scope`: A function that updates some state by calling one or more [`set` functions.](/reference/react/useState#setstate) React immediately calls `scope` with no arguments and marks all state updates scheduled synchronously during the `scope` function call as Transitions. They will be [non-blocking](/reference/react/useTransition#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](/reference/react/useTransition#preventing-unwanted-loading-indicators) #### Returns {/*returns*/} @@ -49,25 +49,25 @@ function TabContainer() { #### Caveats {/*caveats*/} -* `startTransition` does not provide a way to track whether a transition is pending. To show a pending indicator while the transition is ongoing, you need [`useTransition`](/reference/react/useTransition) instead. +* `startTransition` does not provide a way to track whether a Transition is pending. To show a pending indicator while the Transition is ongoing, you need [`useTransition`](/reference/react/useTransition) instead. -* You can wrap an update into a transition only if you have access to the `set` function of that state. If you want to start a transition in response to some prop or a custom Hook return value, try [`useDeferredValue`](/reference/react/useDeferredValue) instead. +* You can wrap an update into a Transition only if you have access to the `set` function of that state. If you want to start a Transition in response to some prop or a custom Hook return value, try [`useDeferredValue`](/reference/react/useDeferredValue) instead. -* The function you pass to `startTransition` must be synchronous. React immediately executes this function, marking all state updates that happen while it executes as transitions. If you try to perform more state updates later (for example, in a timeout), they won't be marked as transitions. +* The function you pass to `startTransition` must be synchronous. React immediately executes this function, marking all state updates that happen while it executes as Transitions. If you try to perform more state updates later (for example, in a timeout), they won't be marked as Transitions. -* A state update marked as a transition will be interrupted by other state updates. For example, if you update a chart component inside a transition, but then start typing into an input while the chart is in the middle of a re-render, React will restart the rendering work on the chart component after handling the input state update. +* A state update marked as a Transition will be interrupted by other state updates. For example, if you update a chart component inside a Transition, but then start typing into an input while the chart is in the middle of a re-render, React will restart the rendering work on the chart component after handling the input state update. * Transition updates can't be used to control text inputs. -* If there are multiple ongoing transitions, React currently batches them together. This is a limitation that will likely be removed in a future release. +* If there are multiple ongoing Transitions, React currently batches them together. This is a limitation that will likely be removed in a future release. --- ## Usage {/*usage*/} -### Marking a state update as a non-blocking transition {/*marking-a-state-update-as-a-non-blocking-transition*/} +### Marking a state update as a non-blocking Transition {/*marking-a-state-update-as-a-non-blocking-transition*/} -You can mark a state update as a *transition* by wrapping it in a `startTransition` call: +You can mark a state update as a *Transition* by wrapping it in a `startTransition` call: ```js {7,9} import { startTransition } from 'react'; @@ -86,12 +86,12 @@ function TabContainer() { Transitions let you keep the user interface updates responsive even on slow devices. -With a transition, your UI stays responsive in the middle of a re-render. For example, if the user clicks a tab but then change their mind and click another tab, they can do that without waiting for the first re-render to finish. +With a Transition, your UI stays responsive in the middle of a re-render. For example, if the user clicks a tab but then change their mind and click another tab, they can do that without waiting for the first re-render to finish. -`startTransition` is very similar to [`useTransition`](/reference/react/useTransition), except that it does not provide the `isPending` flag to track whether a transition is ongoing. You can call `startTransition` when `useTransition` is not available. For example, `startTransition` works outside components, such as from a data library. +`startTransition` is very similar to [`useTransition`](/reference/react/useTransition), except that it does not provide the `isPending` flag to track whether a Transition is ongoing. You can call `startTransition` when `useTransition` is not available. For example, `startTransition` works outside components, such as from a data library. -[Learn about transitions and see examples on the `useTransition` page.](/reference/react/useTransition) +[Learn about Transitions and see examples on the `useTransition` page.](/reference/react/useTransition) diff --git a/src/content/reference/react/use-server.md b/src/content/reference/react/use-server.md index d517873b..3c93564f 100644 --- a/src/content/reference/react/use-server.md +++ b/src/content/reference/react/use-server.md @@ -44,7 +44,7 @@ Instead of individually marking functions with `'use server'`, you can add the d * To import a Server Action from [client code](/reference/react/use-client), the directive must be used on a module level. * Because the underlying network calls are always asynchronous, `'use server'` can only be used on async functions. * Always treat arguments to Server Actions as untrusted input and authorize any mutations. See [security considerations](#security). -* Server Actions should be called in a [transition](/reference/react/useTransition). Server Actions passed to [`
`](/reference/react-dom/components/form#props) or [`formAction`](/reference/react-dom/components/input#props) will automatically be called in a transition. +* Server Actions should be called in a [Transition](/reference/react/useTransition). Server Actions passed to [``](/reference/react-dom/components/form#props) or [`formAction`](/reference/react-dom/components/input#props) will automatically be called in a transition. * Server Actions are designed for mutations that update server-side state; they are not recommended for data fetching. Accordingly, frameworks implementing Server Actions typically process one action at a time and do not have a way to cache the return value. ### Security considerations {/*security*/} @@ -177,7 +177,7 @@ Note that like most Hooks, `useFormState` can only be called in -`useInsertionEffect` allows inserting elements into the DOM before any layout effects fire. +`useInsertionEffect` allows inserting elements into the DOM before any layout Effects fire. ```js useInsertionEffect(setup, dependencies?) @@ -26,7 +26,7 @@ useInsertionEffect(setup, dependencies?) ### `useInsertionEffect(setup, dependencies?)` {/*useinsertioneffect*/} -Call `useInsertionEffect` to insert styles before any effects fire that may need to read layout: +Call `useInsertionEffect` to insert styles before any Effects fire that may need to read layout: ```js import { useInsertionEffect } from 'react'; @@ -44,7 +44,7 @@ function useCSS(rule) { #### Parameters {/*parameters*/} -* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your component is added to the DOM, but before any layout effects fire, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. When your component is removed from the DOM, React will run your cleanup function. +* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your component is added to the DOM, but before any layout Effects fire, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. When your component is removed from the DOM, React will run your cleanup function. * **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison algorithm. If you don't specify the dependencies at all, your Effect will re-run after every re-render of the component. @@ -88,7 +88,7 @@ If you use CSS-in-JS, we recommend a combination of the first two approaches (CS The first problem is not solvable, but `useInsertionEffect` helps you solve the second problem. -Call `useInsertionEffect` to insert the styles before any layout effects fire: +Call `useInsertionEffect` to insert the styles before any layout Effects fire: ```js {4-11} // Inside your CSS-in-JS library diff --git a/src/content/reference/react/useSyncExternalStore.md b/src/content/reference/react/useSyncExternalStore.md index ebaf0987..481690d7 100644 --- a/src/content/reference/react/useSyncExternalStore.md +++ b/src/content/reference/react/useSyncExternalStore.md @@ -57,9 +57,9 @@ The current snapshot of the store which you can use in your rendering logic. * If a different `subscribe` function is passed during a re-render, React will re-subscribe to the store using the newly passed `subscribe` function. You can prevent this by declaring `subscribe` outside the component. -* If the store is mutated during a [non-blocking transition update](/reference/react/useTransition), React will fall back to performing that update as blocking. Specifically, for every transition update, React will call `getSnapshot` a second time just before applying changes to the DOM. If it returns a different value than when it was called originally, React will restart the update from scratch, this time applying it as a blocking update, to ensure that every component on screen is reflecting the same version of the store. +* If the store is mutated during a [non-blocking Transition update](/reference/react/useTransition), React will fall back to performing that update as blocking. Specifically, for every Transition update, React will call `getSnapshot` a second time just before applying changes to the DOM. If it returns a different value than when it was called originally, React will restart the update from scratch, this time applying it as a blocking update, to ensure that every component on screen is reflecting the same version of the store. -* It's not recommended to _suspend_ a render based on a store value returned by `useSyncExternalStore`. The reason is that mutations to the external store cannot be marked as [non-blocking transition updates](/reference/react/useTransition), so they will trigger the nearest [`Suspense` fallback](/reference/react/Suspense), replacing already-rendered content on screen with a loading spinner, which typically makes a poor UX. +* It's not recommended to _suspend_ a render based on a store value returned by `useSyncExternalStore`. The reason is that mutations to the external store cannot be marked as [non-blocking Transition updates](/reference/react/useTransition), so they will trigger the nearest [`Suspense` fallback](/reference/react/Suspense), replacing already-rendered content on screen with a loading spinner, which typically makes a poor UX. For example, the following are discouraged: diff --git a/src/content/reference/react/useTransition.md b/src/content/reference/react/useTransition.md index 7881e1de..77c2cdad 100644 --- a/src/content/reference/react/useTransition.md +++ b/src/content/reference/react/useTransition.md @@ -20,7 +20,7 @@ const [isPending, startTransition] = useTransition() ### `useTransition()` {/*usetransition*/} -Call `useTransition` at the top level of your component to mark some state updates as transitions. +Call `useTransition` at the top level of your component to mark some state updates as Transitions. ```js import { useTransition } from 'react'; @@ -41,14 +41,14 @@ function TabContainer() { `useTransition` returns an array with exactly two items: -1. The `isPending` flag that tells you whether there is a pending transition. -2. The [`startTransition` function](#starttransition) that lets you mark a state update as a transition. +1. The `isPending` flag that tells you whether there is a pending Transition. +2. The [`startTransition` function](#starttransition) that lets you mark a state update as a Transition. --- ### `startTransition` function {/*starttransition*/} -The `startTransition` function returned by `useTransition` lets you mark a state update as a transition. +The `startTransition` function returned by `useTransition` lets you mark a state update as a Transition. ```js {6,8} function TabContainer() { @@ -66,7 +66,7 @@ function TabContainer() { #### Parameters {/*starttransition-parameters*/} -* `scope`: A function that updates some state by calling one or more [`set` functions.](/reference/react/useState#setstate) React immediately calls `scope` with no parameters and marks all state updates scheduled synchronously during the `scope` function call as transitions. They will be [non-blocking](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](#preventing-unwanted-loading-indicators) +* `scope`: A function that updates some state by calling one or more [`set` functions.](/reference/react/useState#setstate) React immediately calls `scope` with no parameters and marks all state updates scheduled synchronously during the `scope` function call as Transitions. They will be [non-blocking](#marking-a-state-update-as-a-non-blocking-transition) and [will not display unwanted loading indicators.](#preventing-unwanted-loading-indicators) #### Returns {/*starttransition-returns*/} @@ -74,25 +74,25 @@ function TabContainer() { #### Caveats {/*starttransition-caveats*/} -* `useTransition` is a Hook, so it can only be called inside components or custom Hooks. If you need to start a transition somewhere else (for example, from a data library), call the standalone [`startTransition`](/reference/react/startTransition) instead. +* `useTransition` is a Hook, so it can only be called inside components or custom Hooks. If you need to start a Transition somewhere else (for example, from a data library), call the standalone [`startTransition`](/reference/react/startTransition) instead. -* You can wrap an update into a transition only if you have access to the `set` function of that state. If you want to start a transition in response to some prop or a custom Hook value, try [`useDeferredValue`](/reference/react/useDeferredValue) instead. +* You can wrap an update into a Transition only if you have access to the `set` function of that state. If you want to start a Transition in response to some prop or a custom Hook value, try [`useDeferredValue`](/reference/react/useDeferredValue) instead. -* The function you pass to `startTransition` must be synchronous. React immediately executes this function, marking all state updates that happen while it executes as transitions. If you try to perform more state updates later (for example, in a timeout), they won't be marked as transitions. +* The function you pass to `startTransition` must be synchronous. React immediately executes this function, marking all state updates that happen while it executes as Transitions. If you try to perform more state updates later (for example, in a timeout), they won't be marked as Transitions. -* A state update marked as a transition will be interrupted by other state updates. For example, if you update a chart component inside a transition, but then start typing into an input while the chart is in the middle of a re-render, React will restart the rendering work on the chart component after handling the input update. +* A state update marked as a Transition will be interrupted by other state updates. For example, if you update a chart component inside a Transition, but then start typing into an input while the chart is in the middle of a re-render, React will restart the rendering work on the chart component after handling the input update. * Transition updates can't be used to control text inputs. -* If there are multiple ongoing transitions, React currently batches them together. This is a limitation that will likely be removed in a future release. +* If there are multiple ongoing Transitions, React currently batches them together. This is a limitation that will likely be removed in a future release. --- ## Usage {/*usage*/} -### Marking a state update as a non-blocking transition {/*marking-a-state-update-as-a-non-blocking-transition*/} +### Marking a state update as a non-blocking Transition {/*marking-a-state-update-as-a-non-blocking-transition*/} -Call `useTransition` at the top level of your component to mark state updates as non-blocking *transitions*. +Call `useTransition` at the top level of your component to mark state updates as non-blocking *Transitions*. ```js [[1, 4, "isPending"], [2, 4, "startTransition"]] import { useState, useTransition } from 'react'; @@ -105,10 +105,10 @@ function TabContainer() { `useTransition` returns an array with exactly two items: -1. The `isPending` flag that tells you whether there is a pending transition. -2. The `startTransition` function that lets you mark a state update as a transition. +1. The `isPending` flag that tells you whether there is a pending Transition. +2. The `startTransition` function that lets you mark a state update as a Transition. -You can then mark a state update as a transition like this: +You can then mark a state update as a Transition like this: ```js {6,8} function TabContainer() { @@ -126,15 +126,15 @@ function TabContainer() { Transitions let you keep the user interface updates responsive even on slow devices. -With a transition, your UI stays responsive in the middle of a re-render. For example, if the user clicks a tab but then change their mind and click another tab, they can do that without waiting for the first re-render to finish. +With a Transition, your UI stays responsive in the middle of a re-render. For example, if the user clicks a tab but then change their mind and click another tab, they can do that without waiting for the first re-render to finish. -#### Updating the current tab in a transition {/*updating-the-current-tab-in-a-transition*/} +#### Updating the current tab in a Transition {/*updating-the-current-tab-in-a-transition*/} In this example, the "Posts" tab is **artificially slowed down** so that it takes at least a second to render. -Click "Posts" and then immediately click "Contact". Notice that this interrupts the slow render of "Posts". The "Contact" tab shows immediately. Because this state update is marked as a transition, a slow re-render did not freeze the user interface. +Click "Posts" and then immediately click "Contact". Notice that this interrupts the slow render of "Posts". The "Contact" tab shows immediately. Because this state update is marked as a Transition, a slow re-render did not freeze the user interface. @@ -269,11 +269,11 @@ b { display: inline-block; margin-right: 10px; } -#### Updating the current tab without a transition {/*updating-the-current-tab-without-a-transition*/} +#### Updating the current tab without a Transition {/*updating-the-current-tab-without-a-transition*/} -In this example, the "Posts" tab is also **artificially slowed down** so that it takes at least a second to render. Unlike in the previous example, this state update is **not a transition.** +In this example, the "Posts" tab is also **artificially slowed down** so that it takes at least a second to render. Unlike in the previous example, this state update is **not a Transition.** -Click "Posts" and then immediately click "Contact". Notice that the app freezes while rendering the slowed down tab, and the UI becomes unresponsive. This state update is not a transition, so a slow re-render freezed the user interface. +Click "Posts" and then immediately click "Contact". Notice that the app freezes while rendering the slowed down tab, and the UI becomes unresponsive. This state update is not a Transition, so a slow re-render freezed the user interface. @@ -409,9 +409,9 @@ b { display: inline-block; margin-right: 10px; } --- -### Updating the parent component in a transition {/*updating-the-parent-component-in-a-transition*/} +### Updating the parent component in a Transition {/*updating-the-parent-component-in-a-transition*/} -You can update a parent component's state from the `useTransition` call, too. For example, this `TabButton` component wraps its `onClick` logic in a transition: +You can update a parent component's state from the `useTransition` call, too. For example, this `TabButton` component wraps its `onClick` logic in a Transition: ```js {8-10} export default function TabButton({ children, isActive, onClick }) { @@ -431,7 +431,7 @@ export default function TabButton({ children, isActive, onClick }) { } ``` -Because the parent component updates its state inside the `onClick` event handler, that state update gets marked as a transition. This is why, like in the earlier example, you can click on "Posts" and then immediately click "Contact". Updating the selected tab is marked as a transition, so it does not block user interactions. +Because the parent component updates its state inside the `onClick` event handler, that state update gets marked as a Transition. This is why, like in the earlier example, you can click on "Posts" and then immediately click "Contact". Updating the selected tab is marked as a Transition, so it does not block user interactions. @@ -560,9 +560,9 @@ b { display: inline-block; margin-right: 10px; } --- -### Displaying a pending visual state during the transition {/*displaying-a-pending-visual-state-during-the-transition*/} +### Displaying a pending visual state during the Transition {/*displaying-a-pending-visual-state-during-the-transition*/} -You can use the `isPending` boolean value returned by `useTransition` to indicate to the user that a transition is in progress. For example, the tab button can have a special "pending" visual state: +You can use the `isPending` boolean value returned by `useTransition` to indicate to the user that a Transition is in progress. For example, the tab button can have a special "pending" visual state: ```js {4-6} function TabButton({ children, isActive, onClick }) { @@ -1087,11 +1087,11 @@ b { display: inline-block; margin-right: 10px; } -[Read more about using transitions with Suspense.](/reference/react/Suspense#preventing-already-revealed-content-from-hiding) +[Read more about using Transitions with Suspense.](/reference/react/Suspense#preventing-already-revealed-content-from-hiding) -Transitions will only "wait" long enough to avoid hiding *already revealed* content (like the tab container). If the Posts tab had a [nested `` boundary,](/reference/react/Suspense#revealing-nested-content-as-it-loads) the transition would not "wait" for it. +Transitions will only "wait" long enough to avoid hiding *already revealed* content (like the tab container). If the Posts tab had a [nested `` boundary,](/reference/react/Suspense#revealing-nested-content-as-it-loads) the Transition would not "wait" for it. @@ -1099,7 +1099,7 @@ Transitions will only "wait" long enough to avoid hiding *already revealed* cont ### Building a Suspense-enabled router {/*building-a-suspense-enabled-router*/} -If you're building a React framework or a router, we recommend marking page navigations as transitions. +If you're building a React framework or a router, we recommend marking page navigations as Transitions. ```js {3,6,8} function Router() { @@ -1119,7 +1119,7 @@ This is recommended for two reasons: - [Transitions are interruptible,](#marking-a-state-update-as-a-non-blocking-transition) which lets the user click away without waiting for the re-render to complete. - [Transitions prevent unwanted loading indicators,](#preventing-unwanted-loading-indicators) which lets the user avoid jarring jumps on navigation. -Here is a tiny simplified router example using transitions for navigations. +Here is a tiny simplified router example using Transitions for navigations. @@ -1495,7 +1495,7 @@ main { -[Suspense-enabled](/reference/react/Suspense) routers are expected to wrap the navigation updates into transitions by default. +[Suspense-enabled](/reference/react/Suspense) routers are expected to wrap the navigation updates into Transitions by default. @@ -1598,15 +1598,15 @@ root.render( ## Troubleshooting {/*troubleshooting*/} -### Updating an input in a transition doesn't work {/*updating-an-input-in-a-transition-doesnt-work*/} +### Updating an input in a Transition doesn't work {/*updating-an-input-in-a-transition-doesnt-work*/} -You can't use a transition for a state variable that controls an input: +You can't use a Transition for a state variable that controls an input: ```js {4,10} const [text, setText] = useState(''); // ... function handleChange(e) { - // ❌ Can't use transitions for controlled input state + // ❌ Can't use Transitions for controlled input state startTransition(() => { setText(e.target.value); }); @@ -1615,16 +1615,16 @@ function handleChange(e) { return ; ``` -This is because transitions are non-blocking, but updating an input in response to the change event should happen synchronously. If you want to run a transition in response to typing, you have two options: +This is because Transitions are non-blocking, but updating an input in response to the change event should happen synchronously. If you want to run a Transition in response to typing, you have two options: -1. You can declare two separate state variables: one for the input state (which always updates synchronously), and one that you will update in a transition. This lets you control the input using the synchronous state, and pass the transition state variable (which will "lag behind" the input) to the rest of your rendering logic. +1. You can declare two separate state variables: one for the input state (which always updates synchronously), and one that you will update in a Transition. This lets you control the input using the synchronous state, and pass the Transition state variable (which will "lag behind" the input) to the rest of your rendering logic. 2. Alternatively, you can have one state variable, and add [`useDeferredValue`](/reference/react/useDeferredValue) which will "lag behind" the real value. It will trigger non-blocking re-renders to "catch up" with the new value automatically. --- -### React doesn't treat my state update as a transition {/*react-doesnt-treat-my-state-update-as-a-transition*/} +### React doesn't treat my state update as a Transition {/*react-doesnt-treat-my-state-update-as-a-transition*/} -When you wrap a state update in a transition, make sure that it happens *during* the `startTransition` call: +When you wrap a state update in a Transition, make sure that it happens *during* the `startTransition` call: ```js startTransition(() => { @@ -1635,7 +1635,7 @@ startTransition(() => { The function you pass to `startTransition` must be synchronous. -You can't mark an update as a transition like this: +You can't mark an update as a Transition like this: ```js startTransition(() => { @@ -1657,7 +1657,7 @@ setTimeout(() => { }, 1000); ``` -Similarly, you can't mark an update as a transition like this: +Similarly, you can't mark an update as a Transition like this: ```js startTransition(async () => { @@ -1698,7 +1698,7 @@ startTransition(() => { console.log(3); ``` -**It is expected to print 1, 2, 3.** The function you pass to `startTransition` does not get delayed. Unlike with the browser `setTimeout`, it does not run the callback later. React executes your function immediately, but any state updates scheduled *while it is running* are marked as transitions. You can imagine that it works like this: +**It is expected to print 1, 2, 3.** The function you pass to `startTransition` does not get delayed. Unlike with the browser `setTimeout`, it does not run the callback later. React executes your function immediately, but any state updates scheduled *while it is running* are marked as Transitions. You can imagine that it works like this: ```js // A simplified version of how React works @@ -1713,7 +1713,7 @@ function startTransition(scope) { function setState() { if (isInsideTransition) { - // ... schedule a transition state update ... + // ... schedule a Transition state update ... } else { // ... schedule an urgent state update ... } diff --git a/src/content/reference/rules/components-and-hooks-must-be-pure.md b/src/content/reference/rules/components-and-hooks-must-be-pure.md index d80207c7..3112ea03 100644 --- a/src/content/reference/rules/components-and-hooks-must-be-pure.md +++ b/src/content/reference/rules/components-and-hooks-must-be-pure.md @@ -3,7 +3,7 @@ title: Components and Hooks must be pure --- -Pure functions only perform a calculation and nothing more. It makes your code easier to understand, debug, and allows React to automatically optimize your components and hooks correctly. +Pure functions only perform a calculation and nothing more. It makes your code easier to understand, debug, and allows React to automatically optimize your components and Hooks correctly. @@ -18,7 +18,7 @@ One of the key concepts that makes React, _React_ is _purity_. A pure component * **Idempotent** – You [always get the same result everytime](/learn/keeping-components-pure#purity-components-as-formulas) you run it with the same inputs – props, state, context for component inputs; and arguments for hook inputs. * **Has no side effects in render** – Code with side effects should run [**separately from rendering**](#how-does-react-run-your-code). For example as an [event handler](/learn/responding-to-events) – where the user interacts with the UI and causes it to update; or as an [Effect](/reference/react/useEffect) – which runs after render. -* **Does not mutate non-local values**: Components and hooks should [never modify values that aren't created locally](#mutation) in render. +* **Does not mutate non-local values**: Components and Hooks should [never modify values that aren't created locally](#mutation) in render. When render is kept pure, React can understand how to prioritize which updates are most important for the user to see first. This is made possible because of render purity: since components don't have side effects [in render](#how-does-react-run-your-code), React can pause rendering components that aren't as important to update, and only come back to them later when it's needed. @@ -68,7 +68,7 @@ function Dropdown() { --- -## Components and hooks must be idempotent {/*components-and-hooks-must-be-idempotent*/} +## Components and Hooks must be idempotent {/*components-and-hooks-must-be-idempotent*/} Components must always return the same output with respect to their inputs – props, state, and context. This is known as _idempotency_. [Idempotency](https://en.wikipedia.org/wiki/Idempotence) is a term popularized in functional programming. It refers to the idea that you [always get the same result everytime](learn/keeping-components-pure) you run that piece of code with the same inputs. @@ -307,7 +307,7 @@ function useIconStyle(icon) { } ``` -If you were to mutate the hooks arguments, the custom hook's memoization will become incorrect, so it's important to avoid doing that. +If you were to mutate the Hooks arguments, the custom hook's memoization will become incorrect, so it's important to avoid doing that. ```js {4} style = useIconStyle(icon); // `style` is memoized based on `icon` @@ -321,7 +321,7 @@ icon = { ...icon, enabled: false }; // Good: ✅ make a copy instead style = useIconStyle(icon); // new value of `style` is calculated ``` -Similarly, it's important to not modify the return values of hooks, as they may have been memoized. +Similarly, it's important to not modify the return values of Hooks, as they may have been memoized. --- @@ -361,4 +361,4 @@ function Page({ colour }) { ); } -``` \ No newline at end of file +``` diff --git a/src/content/reference/rules/react-calls-components-and-hooks.md b/src/content/reference/rules/react-calls-components-and-hooks.md index f82b3815..3d865b4f 100644 --- a/src/content/reference/rules/react-calls-components-and-hooks.md +++ b/src/content/reference/rules/react-calls-components-and-hooks.md @@ -3,7 +3,7 @@ title: React calls Components and Hooks --- -React is responsible for rendering components and hooks when necessary to optimize the user experience. It is declarative: you tell React what to render in your component’s logic, and React will figure out how best to display it to your user. +React is responsible for rendering components and Hooks when necessary to optimize the user experience. It is declarative: you tell React what to render in your component’s logic, and React will figure out how best to display it to your user. @@ -27,7 +27,7 @@ function BlogPost() { } ``` -If a component contains hooks, it's easy to violate the [Rules of Hooks](/reference/rules/rules-of-hooks) when components are called directly in a loop or conditionally. +If a component contains Hooks, it's easy to violate the [Rules of Hooks](/reference/rules/rules-of-hooks) when components are called directly in a loop or conditionally. Letting React orchestrate rendering also allows a number of benefits: @@ -39,30 +39,30 @@ Letting React orchestrate rendering also allows a number of benefits: --- -## Never pass around hooks as regular values {/*never-pass-around-hooks-as-regular-values*/} +## Never pass around Hooks as regular values {/*never-pass-around-hooks-as-regular-values*/} -Hooks should only be called inside of components or hooks. Never pass it around as a regular value. +Hooks should only be called inside of components or Hooks. Never pass it around as a regular value. Hooks allow you to augment a component with React features. They should always be called as a function, and never passed around as a regular value. This enables _local reasoning_, or the ability for developers to understand everything a component can do by looking at that component in isolation. Breaking this rule will cause React to not automatically optimize your component. -### Don't dynamically mutate a hook {/*dont-dynamically-mutate-a-hook*/} +### Don't dynamically mutate a Hook {/*dont-dynamically-mutate-a-hook*/} -Hooks should be as "static" as possible. This means you shouldn't dynamically mutate them. For example, this means you shouldn't write higher order hooks: +Hooks should be as "static" as possible. This means you shouldn't dynamically mutate them. For example, this means you shouldn't write higher order Hooks: ```js {2} function ChatInput() { - const useDataWithLogging = withLogging(useData); // 🔴 Bad: don't write higher order hooks + const useDataWithLogging = withLogging(useData); // 🔴 Bad: don't write higher order Hooks const data = useDataWithLogging(); } ``` -Hooks should be immutable and not be mutated. Instead of mutating a hook dynamically, create a static version of the hook with the desired functionality. +Hooks should be immutable and not be mutated. Instead of mutating a Hook dynamically, create a static version of the Hook with the desired functionality. ```js {2,6} function ChatInput() { - const data = useDataWithLogging(); // ✅ Good: Create a new version of the hook + const data = useDataWithLogging(); // ✅ Good: Create a new version of the Hook } function useDataWithLogging() { @@ -70,17 +70,17 @@ function useDataWithLogging() { } ``` -### Don't dynamically use hooks {/*dont-dynamically-use-hooks*/} +### Don't dynamically use Hooks {/*dont-dynamically-use-hooks*/} -Hooks should also not be dynamically used: for example, instead of doing dependency injection in a component by passing a hook as a value: +Hooks should also not be dynamically used: for example, instead of doing dependency injection in a component by passing a Hook as a value: ```js {2} function ChatInput() { - return