diff --git a/public/images/docs/diagrams/use_client_module_dependency.dark.png b/public/images/docs/diagrams/use_client_module_dependency.dark.png new file mode 100644 index 000000000..c50e7308b Binary files /dev/null and b/public/images/docs/diagrams/use_client_module_dependency.dark.png differ diff --git a/public/images/docs/diagrams/use_client_module_dependency.png b/public/images/docs/diagrams/use_client_module_dependency.png new file mode 100644 index 000000000..d535246f7 Binary files /dev/null and b/public/images/docs/diagrams/use_client_module_dependency.png differ diff --git a/public/images/docs/diagrams/use_client_render_tree.dark.png b/public/images/docs/diagrams/use_client_render_tree.dark.png new file mode 100644 index 000000000..8d3e6a484 Binary files /dev/null and b/public/images/docs/diagrams/use_client_render_tree.dark.png differ diff --git a/public/images/docs/diagrams/use_client_render_tree.png b/public/images/docs/diagrams/use_client_render_tree.png new file mode 100644 index 000000000..ad3840681 Binary files /dev/null and b/public/images/docs/diagrams/use_client_render_tree.png differ diff --git a/src/components/Layout/getRouteMeta.tsx b/src/components/Layout/getRouteMeta.tsx index d22947847..3564dd738 100644 --- a/src/components/Layout/getRouteMeta.tsx +++ b/src/components/Layout/getRouteMeta.tsx @@ -58,13 +58,13 @@ export interface RouteMeta { order?: number; } -type TravesalContext = RouteMeta & { +type TraversalContext = RouteMeta & { currentIndex: number; }; export function getRouteMeta(cleanedPath: string, routeTree: RouteItem) { const breadcrumbs = getBreadcrumbs(cleanedPath, routeTree); - const ctx: TravesalContext = { + const ctx: TraversalContext = { currentIndex: 0, }; buildRouteMeta(cleanedPath, routeTree, ctx); @@ -79,7 +79,7 @@ export function getRouteMeta(cleanedPath: string, routeTree: RouteItem) { function buildRouteMeta( searchPath: string, currentRoute: RouteItem, - ctx: TravesalContext + ctx: TraversalContext ) { ctx.currentIndex++; diff --git a/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md b/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md index a6592fd3b..5071af6ec 100644 --- a/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md +++ b/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md @@ -74,7 +74,7 @@ Making plain JavaScript in React components reactive requires a compiler with a ## Offscreen Rendering {/*offscreen-rendering*/} -Offscreen rendering is an upcoming capability in React for rendering screens in the background without additional performance overhead. You can think of it as a version of the [`content-visiblity` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility) that works not only for DOM elements but React components, too. During our research, we've discovered a variety of use cases: +Offscreen rendering is an upcoming capability in React for rendering screens in the background without additional performance overhead. You can think of it as a version of the [`content-visibility` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility) that works not only for DOM elements but React components, too. During our research, we've discovered a variety of use cases: - A router can prerender screens in the background so that when a user navigates to them, they're instantly available. - A tab switching component can preserve the state of hidden tabs, so the user can switch between them without losing their progress. diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 7c6023220..dfffc74f5 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -273,7 +273,7 @@ export async function deliverMessage(message) { -[//]: # 'Uncomment the next line, and delete this line after the `useOptimisitc` reference documentatino page is published' +[//]: # 'Uncomment the next line, and delete this line after the `useOptimistic` reference documentatino page is published' [//]: # 'To learn more about the `useOptimistic` Hook see the [reference documentation](/reference/react/hooks/useOptimistic).' ### Handling form submission errors {/*handling-form-submission-errors*/} diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 6895575ad..bf311527f 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -632,7 +632,7 @@ class Form extends Component { return ( <> -

Hola, {this.state.name}. +

Hola, {this.state.name}.

); } diff --git a/src/content/reference/react/cache.md b/src/content/reference/react/cache.md index 65d95ab76..735560636 100644 --- a/src/content/reference/react/cache.md +++ b/src/content/reference/react/cache.md @@ -309,7 +309,7 @@ async function DemoProfile() { React only provides cache access to the memoized function in a component. When calling `getUser` outside of a component, it will still evaluate the function but not read or update the cache. -This is because cache access is provided through a [context](/learn/passing-data-deeply-with-context) which is only accessibile from a component. +This is because cache access is provided through a [context](/learn/passing-data-deeply-with-context) which is only accessible from a component. diff --git a/src/content/reference/react/directives.md b/src/content/reference/react/directives.md index 861ad781e..c7d219cb1 100644 --- a/src/content/reference/react/directives.md +++ b/src/content/reference/react/directives.md @@ -19,5 +19,5 @@ Las directivas proporcionan instrucciones para [bundlers compatibles con React S ## Directivas de código fuente {/*source-code-directives*/} -* [`'use client'`](/reference/react/use-client) marca los ficheros fuente cuyos componentes se ejecutan en el cliente. +* [`'use client'`](/reference/react/use-client) te permite marcar qué código se ejecuta en el cliente. * [`'use server'`](/reference/react/use-server) marca funciones del lado del servidor que pueden ser llamadas desde código del lado del cliente. diff --git a/src/content/reference/react/experimental_taintUniqueValue.md b/src/content/reference/react/experimental_taintUniqueValue.md index aeee7456c..e8226d92f 100644 --- a/src/content/reference/react/experimental_taintUniqueValue.md +++ b/src/content/reference/react/experimental_taintUniqueValue.md @@ -131,7 +131,7 @@ In this example, the constant `password` is tainted. Then `password` is used to Other similar ways of deriving new values from tainted values like concatenating it into a larger string, converting it to base64, or returning a substring create untained values. -Tainting only protects against simple mistakes like explictly passing secret values to the client. Mistakes in calling the `taintUniqueValue` like using a global store outside of React, without the corresponding lifetime object, can cause the tainted value to become untainted. Tainting is a layer of protection; a secure app will have multiple layers of protection, well designed APIs, and isolation patterns. +Tainting only protects against simple mistakes like explicitly passing secret values to the client. Mistakes in calling the `taintUniqueValue` like using a global store outside of React, without the corresponding lifetime object, can cause the tainted value to become untainted. Tainting is a layer of protection; a secure app will have multiple layers of protection, well designed APIs, and isolation patterns. diff --git a/src/content/reference/react/hooks.md b/src/content/reference/react/hooks.md new file mode 100644 index 000000000..cec71ce8f --- /dev/null +++ b/src/content/reference/react/hooks.md @@ -0,0 +1,139 @@ +--- +title: "Built-in React Hooks" +--- + + + +*Hooks* let you use different React features from your components. You can either use the built-in Hooks or combine them to build your own. This page lists all built-in Hooks in React. + + + +--- + +## State Hooks {/*state-hooks*/} + +*State* lets a component ["remember" information like user input.](/learn/state-a-components-memory) For example, a form component can use state to store the input value, while an image gallery component can use state to store the selected image index. + +To add state to a component, use one of these Hooks: + +* [`useState`](/reference/react/useState) declares a state variable that you can update directly. +* [`useReducer`](/reference/react/useReducer) declares a state variable with the update logic inside a [reducer function.](/learn/extracting-state-logic-into-a-reducer) + +```js +function ImageGallery() { + const [index, setIndex] = useState(0); + // ... +``` + +--- + +## Context Hooks {/*context-hooks*/} + +*Context* lets a component [receive information from distant parents without passing it as props.](/learn/passing-props-to-a-component) For example, your app's top-level component can pass the current UI theme to all components below, no matter how deep. + +* [`useContext`](/reference/react/useContext) reads and subscribes to a context. + +```js +function Button() { + const theme = useContext(ThemeContext); + // ... +``` + +--- + +## Ref Hooks {/*ref-hooks*/} + +*Refs* let a component [hold some information that isn't used for rendering,](/learn/referencing-values-with-refs) like a DOM node or a timeout ID. Unlike with state, updating a ref does not re-render your component. Refs are an "escape hatch" from the React paradigm. They are useful when you need to work with non-React systems, such as the built-in browser APIs. + +* [`useRef`](/reference/react/useRef) declares a ref. You can hold any value in it, but most often it's used to hold a DOM node. +* [`useImperativeHandle`](/reference/react/useImperativeHandle) lets you customize the ref exposed by your component. This is rarely used. + +```js +function Form() { + const inputRef = useRef(null); + // ... +``` + +--- + +## Effect Hooks {/*effect-hooks*/} + +*Effects* let a component [connect to and synchronize with external systems.](/learn/synchronizing-with-effects) This includes dealing with network, browser DOM, animations, widgets written using a different UI library, and other non-React code. + +* [`useEffect`](/reference/react/useEffect) connects a component to an external system. + +```js +function ChatRoom({ roomId }) { + useEffect(() => { + const connection = createConnection(roomId); + connection.connect(); + return () => connection.disconnect(); + }, [roomId]); + // ... +``` + +Effects are an "escape hatch" from the React paradigm. Don't use Effects to orchestrate the data flow of your application. If you're not interacting with an external system, [you might not need an Effect.](/learn/you-might-not-need-an-effect) + +There are two rarely used variations of `useEffect` with differences in timing: + +* [`useLayoutEffect`](/reference/react/useLayoutEffect) fires before the browser repaints the screen. You can measure layout here. +* [`useInsertionEffect`](/reference/react/useInsertionEffect) fires before React makes changes to the DOM. Libraries can insert dynamic CSS here. + +--- + +## Performance Hooks {/*performance-hooks*/} + +A common way to optimize re-rendering performance is to skip unnecessary work. For example, you can tell React to reuse a cached calculation or to skip a re-render if the data has not changed since the previous render. + +To skip calculations and unnecessary re-rendering, use one of these Hooks: + +- [`useMemo`](/reference/react/useMemo) lets you cache the result of an expensive calculation. +- [`useCallback`](/reference/react/useCallback) lets you cache a function definition before passing it down to an optimized component. + +```js +function TodoList({ todos, tab, theme }) { + const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]); + // ... +} +``` + +Sometimes, you can't skip re-rendering because the screen actually needs to update. In that case, you can improve performance by separating blocking updates that must be synchronous (like typing into an input) from non-blocking updates which don't need to block the user interface (like updating a chart). + +To prioritize rendering, use one of these Hooks: + +- [`useTransition`](/reference/react/useTransition) lets you mark a state transition as non-blocking and allow other updates to interrupt it. +- [`useDeferredValue`](/reference/react/useDeferredValue) lets you defer updating a non-critical part of the UI and let other parts update first. + +--- + +## Resource Hooks {/*resource-hooks*/} + +*Resources* can be accessed by a component without having them as part of their state. For example, a component can read a message from a Promise or read styling information from a context. + +To read a value from a resource, use this Hook: + +- [`use`](/reference/react/use) lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context). + +```js +function MessageComponent({ messagePromise }) { + const message = use(messagePromise); + const theme = use(ThemeContext); + // ... +} +``` + +--- + +## Other Hooks {/*other-hooks*/} + +These Hooks are mostly useful to library authors and aren't commonly used in the application code. + +- [`useDebugValue`](/reference/react/useDebugValue) lets you customize the label React DevTools displays for your custom Hook. +- [`useId`](/reference/react/useId) lets a component associate a unique ID with itself. Typically used with accessibility APIs. +- [`useSyncExternalStore`](/reference/react/useSyncExternalStore) lets a component subscribe to an external store. + +--- + +## Your own Hooks {/*your-own-hooks*/} + +You can also [define your own custom Hooks](/learn/reusing-logic-with-custom-hooks#extracting-your-own-custom-hook-from-a-component) as JavaScript functions. diff --git a/src/content/reference/react/index.md b/src/content/reference/react/index.md index 4fbb65b61..05d521a2d 100644 --- a/src/content/reference/react/index.md +++ b/src/content/reference/react/index.md @@ -1,139 +1,30 @@ --- -title: "Hooks integrados de React" +title: React Reference Overview --- - -Los *Hooks* te permiten usar diferentes funciones de React desde tus componentes. Puedes usar los Hooks integrados o combinarlos para construir tu propio Hook. Esta página lista todos los *Hooks integrados* en React. - +This section provides detailed reference documentation for working with React. +For an introduction to React, please visit the [Learn](/learn) section. ---- - -## Hooks de estado {/*state-hooks*/} - -El *estado* permite que un componente ["recuerde" información como la entrada de un usuario.](/learn/state-a-components-memory) Por ejemplo, un componente de formulario puede utilizar un estado para guardar la entrada del valor mientras que un componente de galería de imágenes puede utilizar un estado para guardar el índice de la imagen seleccionada. - -Para añadir un estado a un componente, usa uno de estos Hooks: - -* [`useState`](/reference/react/useState) declara una variable de estado que puedes actualizar directamente. -* [`useReducer`](/reference/react/useReducer) declara una variable de estado con la lógica de actualización dentro de una [función reductora.](/learn/extracting-state-logic-into-a-reducer) - -```js -function ImageGallery() { - const [index, setIndex] = useState(0); - // ... -``` - ---- - -## Hooks de contexto {/*context-hooks*/} - -El *contexto* permite a un componente [recibir información de padres lejanos sin pasarlas como props.](/learn/passing-props-to-a-component) Por ejemplo, el componente en el nivel superior de tu aplicación puede pasar el actual tema de la UI a todos los componentes dentro, sin importar la profundidad dentro del componente. - -* [`useContext`](/reference/react/useContext) lee y se subscribe a un contexto. - -```js -function Button() { - const theme = useContext(ThemeContext); - // ... -``` - ---- - -## Hooks de refs {/*ref-hooks*/} - -Las *refs* le permiten a un componente [mantener alguna información que no es utilizada para el renderizado](/learn/referencing-values-with-refs) como un nodo del DOM o el ID de un *timeout*. A diferencia del estado, actualizar una *ref* no vuelve a renderizar tu componente. Las *refs* son una "puerta de escape" del paradigma de React. Son útiles cuando necesitas trabajar con sistemas distintos de React, como las APIs integradas del navegador. - -* [`useRef`](/reference/react/useRef) declara una ref. Puede contener cualquier valor, pero la mayoría de las veces se utiliza para contener un nodo del DOM. -* [`useImperativeHandle`](/reference/react/useImperativeHandle) permite personalizar la *ref* expuesta por tu componente. Esto rara vez se usa. - -```js -function Form() { - const inputRef = useRef(null); - // ... -``` - ---- - -## Hooks de Efecto {/*effect-hooks*/} - -El *Hook de Efecto* permite a un componente [conectarse y sincronizarse con sistemas externos.](/learn/synchronizing-with-effects) Esto incluye lidiar con la red, el DOM del navegador, animaciones, *widgets* escritos utilizando una biblioteca de UI diferente y otro código que no es de React. - -* [`useEffect`](/reference/react/useEffect) conecta un componente a un sistema externo. - -```js -function ChatRoom({ roomId }) { - useEffect(() => { - const connection = createConnection(roomId); - connection.connect(); - return () => connection.disconnect(); - }, [roomId]); - // ... -``` +Our The React reference documentation is broken down into functional subsections: -Los *Hooks de Efecto* son una "puerta de escape" del paradigma de React. No utilices los *Efectos* para guiar el flujo de los datos de tu aplicación. Si no estás interactuando con un sistema externo, [puede que no necesites un Hook de Efecto.](/learn/you-might-not-need-an-effect) +## React {/*react*/} +Programmatic React features: +* [Hooks](/reference/react/hooks) - Use different React features from your components. +* [Components](/reference/react/components) - Documents built-in components that you can use in your JSX. +* [APIs](/reference/react/apis) - APIs that are useful for defining components. +* [Directives](/reference/react/directives) - Provide instructions to bundlers compatible with React Server Components. -Hay dos variaciones poco usadas de `useEffect` con diferencias en los tiempos en que se llaman: - -* [`useLayoutEffect`](/reference/react/useLayoutEffect) se activa antes de que el navegador vuelva a pintar la pantalla. Aquí puedes hacer cálculos de maquetación (*layout*). -* [`useInsertionEffect`](/reference/react/useInsertionEffect) se activa antes de que React haga cambios en el DOM. Aquí las bibliotecas pueden insertar CSS dinámico. - ---- - -## Hooks de rendimiento {/*performance-hooks*/} - -Una forma común de optimizar el rendimiento del rerenderizado es evitar trabajo innecesario. Por ejemplo, puedes decirle a React que reutilice un cálculo guardado en caché o que se salte un rerenderizado si los datos no han cambiado desde el renderizado anterior. - -Para evitar cálculos y renderizados innecesarios, usa uno de estos Hooks: - -- [`useMemo`](/reference/react/useMemo) permite guardar en caché los resultados de un cálculo costoso. -- [`useCallback`](/reference/react/useCallback) permite guardar en caché una función definida antes de pasarla a un componente optimizado. - -```js -function TodoList({ todos, tab, theme }) { - const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]); - // ... -} -``` - -Algunas veces no podrás evitar un rerenderizado porque la pantalla realmente necesita una actualización. En ese caso, puedes mejorar el rendimiento separando las actualizaciones bloqueantes que deben ser síncronas (como al escribir dentro de una entrada de texto) de las actualizaciones no bloqueantes, que no necesitan bloquear la interfaz de usuario (como actualizar un gráfico). - -Para priorizar el renderizado, usa uno de estos Hooks: - -- [`useTransition`](/reference/react/useTransition) permite marcar una transición de estado como no bloqueante y permitir que otras actualizaciones la interrumpan. -- [`useDeferredValue`](/reference/react/useDeferredValue) te permite aplazar la actualización de una parte no crítica de la interfaz de usuario y dejar que otras partes se actualicen primero. - ---- - -## Hooks de recursos {/*resource-hooks*/} - -Un componente puede acceder a *recursos* sin tenerlos como parte de su estado. Por ejemplo, un componente puede leer un mensaje de una Promesa o leer información de estilo de un contexto. - -Para leer un valor de un recurso, utilice este Hook: - -- [`use`](/reference/react/use) te permite leer el valor de un recurso como una [Promesa](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) o [contexto](/learn/passing-data-deeply-with-context). - -```js -function MessageComponent({ messagePromise }) { - const message = use(messagePromise); - const theme = use(ThemeContext); - // ... -} -``` - ---- - -## Otros Hooks {/*other-hooks*/} - -Estos Hooks son mayormente útiles para autores de bibliotecas y no son comúnmente usadas en el código de la aplicación. - -- [`useDebugValue`](/reference/react/useDebugValue) permite personalizar la etiqueta que las Herramientas de Desarrollo de React muestran para tu Hook personalizado. -- [`useId`](/reference/react/useId) permite que un componente se asocie un ID único. Normalmente, se utiliza con las APIs de accesibilidad. -- [`useSyncExternalStore`](/reference/react/useSyncExternalStore) permite que un componente se subscriba a un almacenamiento (*store*) externo. - ---- +## React DOM {/*react-dom*/} +React-dom contains features that are only supported for web applications +(which run in the browser DOM environment). This section is broken into the following: -## Tus propios Hooks {/*your-own-hooks*/} +* [Hooks](/reference/react-dom/hooks) - Hooks for web applications which run in the browser DOM environment. +* [Components](/reference/react-dom/components) - React supports all of the browser built-in HTML and SVG components. +* [APIs](/reference/react-dom) - The `react-dom` package contains methods supported only in web applications. +* [Client APIs](/reference/react-dom/client) - The `react-dom/client` APIs let you render React components on the client (in the browser). +* [Server APIs](/reference/react-dom/server) - The `react-dom/server` APIs let you render React components to HTML on the server. -También puedes [definir tus propios Hooks personalizados](/learn/reusing-logic-with-custom-hooks#extracting-your-own-custom-hook-from-a-component) como funciones JavaScript. +## Legacy APIs {/*legacy-apis*/} +* [Legacy APIs](/reference/react/legacy) - Exported from the react package, but not recommended for use in newly written code. diff --git a/src/content/reference/react/use-client.md b/src/content/reference/react/use-client.md index 8396ada34..4a93bddb4 100644 --- a/src/content/reference/react/use-client.md +++ b/src/content/reference/react/use-client.md @@ -12,7 +12,7 @@ canary: true -`'use client'` marca los archivos fuente cuyos componentes se ejecutan en el cliente. +`'use client'` te permite marcar qué código se ejecuta en el cliente. @@ -24,37 +24,356 @@ canary: true ### `'use client'` {/*use-client*/} -Agrega `'use client';` en la parte superior de un archivo para marcar que este archivo (incluyendo cualquier componente hijo que utilice) se ejecuta en el cliente, independientemente de dónde se importe. +Add `'use client'` at the top of a file to mark the module and its transitive dependencies as client code. -```js +```js {1} 'use client'; import { useState } from 'react'; +import { formatDate } from './formatters'; +import Button from './button'; -export default function RichTextEditor(props) { +export default function RichTextEditor({ timestamp, text }) { + const date = formatDate(timestamp); + // ... + const editButton = + {children} + + ); +} +``` + +```js Copyright.js +export default function Copyright({year}) { + return

©️ {year}

; +} +``` + +```js inspirations.js +export default [ + "Don’t let yesterday take up too much of today.” — Will Rogers", + "Ambition is putting a ladder against the sky.", + "A joy that's shared is a joy made double.", +]; +``` + +```css +.fancy { + font-family: 'Georgia'; +} +.title { + color: #007AA3; + text-decoration: underline; +} +.cursive { + font-style: italic; +} +.small { + font-size: 10px; +} +``` + + + +In the module dependency tree of this example app, the `'use client'` directive in `InspirationGenerator.js` marks that module and all of its transitive dependencies as client modules. The subtree starting at `InspirationGenerator.js` is now marked as client modules. + + +`'use client'` segments the module dependency tree of the React Server Components app, marking `InspirationGenerator.js` and all of its dependencies as client-rendered. + + +During render, the framework will server-render the root component and continue through the [render tree](/learn/understanding-your-ui-as-a-tree#the-render-tree), opting-out of evaluating any code imported from client-marked code. + +The server-rendered portion of the render tree is then sent to the client. The client, with its client code downloaded, then completes rendering the rest of the tree. + + +The render tree for the React Server Components app. `InspirationGenerator` and its child component `FancyText` are components exported from client-marked code and considered Client Components. + + +We introduce the following definitions: + +* **Client Components** are components in a render tree that are rendered on the client. +* **Server Components** are components in a render tree that are rendered on the server. + +Working through the example app, `App`, `FancyText` and `Copyright` are all server-rendered and considered Server Components. As `InspirationGenerator.js` and its transitive dependencies are marked as client code, the component `InspirationGenerator` and its child component `FancyText` are Client Components. + + +#### How is `FancyText` both a Server and a Client Component? {/*how-is-fancytext-both-a-server-and-a-client-component*/} + +By the above definitions, the component `FancyText` is both a Server and Client Component, how can that be? + +First, let's clarify that the term "component" is not very precise. Here are just two ways "component" can be understood: + +1. A "component" can refer to a **component definition**. In most cases this will be a function. + +```js +// This is a definition of a component +function MyComponent() { + return

My Component

+} +``` + +2. A "component" can also refer to a **component usage** of its definition. +```js +import MyComponent from './MyComponent'; + +function App() { + // This is a usage of a component + return ; +} +``` + +Often, the imprecision is not important when explaining concepts, but in this case it is. + +When we talk about Server or Client Components, we are referring to component usages. + +* If the component is defined in a module with a `'use client'` directive, or the component is imported and called in a Client Component, then the component usage is a Client Component. +* Otherwise, the component usage is a Server Component. + + +A render tree illustrates component usages. + +Back to the question of `FancyText`, we see that the component definition does _not_ have a `'use client'` directive and it has two usages. + +The usage of `FancyText` as a child of `App`, marks that usage as a Server Component. When `FancyText` is imported and called under `InspirationGenerator`, that usage of `FancyText` is a Client Component as `InspirationGenerator` contains a `'use client'` directive. + +This means that the component definition for `FancyText` will both be evaluated on the server and also downloaded by the client to render its Client Component usage. + +
+ + + +#### Why is `Copyright` a Server Component? {/*why-is-copyright-a-server-component*/} + +Because `Copyright` is rendered as a child of the Client Component `InspirationGenerator`, you might be surprised that it is a Server Component. + +Recall that `'use client'` defines the boundary between server and client code on the _module dependency tree_, not the render tree. + + +`'use client'` defines the boundary between server and client code on the module dependency tree. + + +In the module dependency tree, we see that `App.js` imports and calls `Copyright` from the `Copyright.js` module. As `Copyright.js` does not contain a `'use client'` directive, the component usage is rendered on the server. `App` is rendered on the server as it is the root component. + +Client Components can render Server Components because you can pass JSX as props. In this case, `InspirationGenerator` receives `Copyright` as [children](/learn/passing-props-to-a-component#passing-jsx-as-children). However, the `InspirationGenerator` module never directly imports the `Copyright` module nor calls the component, all of that is done by `App`. In fact, the `Copyright` component is fully executed before `InspirationGenerator` starts rendering. + +The takeaway is that a parent-child render relationship between components does not guarantee the same render environment. + + + +### When to use `'use client'` {/*when-to-use-use-client*/} + +With `'use client'`, you can determine when components are Client Components. As Server Components are default, here is a brief overview of the advantages and limitations to Server Components to determine when you need to mark something as client rendered. + +For simplicity, we talk about Server Components, but the same principles apply to all code in your app that is server run. + +#### Advantages of Server Components {/*advantages*/} +* Server Components can reduce the amount of code sent and run by the client. Only client modules are bundled and evaluated by the client. +* Server Components benefit from running on the server. They can access the local filesystem and may experience low latency for data fetches and network requests. + +#### Limitations of Server Components {/*limitations*/} +* Server Components cannot support interaction as event handlers must be registered and triggered by a client. + * For example, event handlers like `onClick` can only be defined in Client Components. +* Server Components cannot use most Hooks. + * When Server Components are rendered, their output is essentially a list of components for the client to render. Server Components do not persist in memory after render and cannot have their own state. + +### Serializable types returned by Server Components {/*serializable-types*/} + +As in any React app, parent components pass data to child components. As they are rendered in different environments, passing data from a Server Component to a Client Component requires extra consideration. + +Prop values passed from a Server Component to Client Component must be serializable. + +Serializable props include: +* Primitives + * [string](https://developer.mozilla.org/en-US/docs/Glossary/String) + * [number](https://developer.mozilla.org/en-US/docs/Glossary/Number) + * [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) + * [boolean](https://developer.mozilla.org/en-US/docs/Glossary/Boolean) + * [undefined](https://developer.mozilla.org/en-US/docs/Glossary/Undefined) + * [null](https://developer.mozilla.org/en-US/docs/Glossary/Null) + * [symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol), only symbols registered in the global Symbol registry via [`Symbol.for`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for) +* Iterables containing serializable values + * [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) + * [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) + * [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) + * [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) + * [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) and [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) +* [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) +* Plain [objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object): those created with [object initializers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer), with serializable properties +* Functions that are [server actions](/reference/react/use-server) +* Client or Server Component elements (JSX) +* [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) + +Notably, these are not supported: +* [Functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) that are not exported from client-marked modules or marked with [`'use server'`](/reference/react/use-server) +* [Classes](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Classes_in_JavaScript) +* Objects that are instances of any class (other than the built-ins mentioned) or objects with [a null prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#null-prototype_objects) +* Symbols not registered globally, ex. `Symbol('my new symbol')` + + +## Usage {/*usage*/} + +### Building with interactivity and state {/*building-with-interactivity-and-state*/} + + + +```js App.js +'use client'; + +import { useState } from 'react'; + +export default function Counter({initialValue = 0}) { + const [countValue, setCountValue] = useState(initialValue); + const increment = () => setCountValue(countValue + 1); + const decrement = () => setCountValue(countValue - 1); + return ( + <> +

Count Value: {countValue}

+ + + + ); +} +``` + +
+ +As `Counter` requires both the `useState` hook and event handlers to increment or decrement the value, this component must be a Client Component and will require a `'use client'` directive at the top. + +In contrast, a component that renders UI without interaction will not need to be a Client Component. + +```js +import { readFile } from 'node:fs/promises'; +import Counter from './Counter'; + +export default async function CounterContainer() { + const initialValue = await readFile('/path/to/counter_value'); + return +} ``` -Cuando un archivo marcado con `'use client'` es importado desde un componente de servidor, los [bundlers compatibles](/learn/start-a-new-react-project#bleeding-edge-react-frameworks) manejan la importación como el "punto de corte" entre el código exclusivo del servidor y el código del cliente. Los componentes en o por debajo de este punto en el gráfico del módulo pueden utilizar características exclusivas de React para el cliente, como [`useState`](/reference/react/useState). +For example, `Counter`'s parent component, `CounterContainer`, does not require `'use client'` as it is not interactive and does not use state. In addition, `CounterContainer` must be a Server Component as it reads from the local file system on the server, which is possible only in a Server Component. + +There are also components that don't use any server or client-only features and can be agnostic to where they render. In our earlier example, `FancyText` is one such component. + +```js +export default function FancyText({title, text}) { + return title + ?

{text}

+ :

{text}

+} +``` + +In this case, we don't add the `'use client'` directive, resulting in `FancyText`'s _output_ (rather than its source code) to be sent to the browser when referenced from a Server Component. As demonstrated in the earlier Inspirations app example, `FancyText` is used as both a Server or Client Component, depending on where it is imported and used. + +But if `FancyText`'s HTML output was large relative to its source code (including dependencies), it might be more efficient to force it to always be a Client Component. Components that return a long SVG path string are one case where it may be more efficient to force a component to be a Client Component. + +### Using client APIs {/*using-client-apis*/} + +Your React app may use client-specific APIs, such as the browser's APIs for web storage, audio and video manipulation, and device hardware, among [others](https://developer.mozilla.org/en-US/docs/Web/API). + +In this example, the component uses [DOM APIs](https://developer.mozilla.org/en-US/docs/Glossary/DOM) to manipulate a [`canvas`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas) element. Since those APIs are only available in the browser, it must be marked as a Client Component. + +```js +'use client'; + +import {useRef, useEffect} from 'react'; + +export default function Circle() { + const ref = useRef(null); + useLayoutEffect(() => { + const canvas = ref.current; + const context = canvas.getContext('2d'); + context.reset(); + context.beginPath(); + context.arc(100, 75, 50, 0, 2 * Math.PI); + context.stroke(); + }); + return ; +} +``` -#### Advertencias {/*caveats*/} +### Using third-party libraries {/*using-third-party-libraries*/} -* No es necesario añadir `'use client'` a cada archivo que utiliza características exclusivas de React para el cliente, sólo los archivos que son importados desde archivos de componentes de servidor. `'use client'` marca la _barrera_ entre el código exclusivo del servidor y el código del cliente; cualquier componente más abajo en el árbol se ejecutará automáticamente en el cliente. Para ser renderizados desde componentes de servidor, los componentes exportados desde archivos con `'use client'` deben tener props serializables. -* Cuando se importa un archivo con `'use client'` desde un archivo de servidor, los valores importados pueden ser renderizados como un componente de React o o pasados mediante props a un componete del cliente. Cualqueir otro uso lanzará una excepción. -* Cuando se importa un archivo con `'use client'` desde otro archivo del cliente, la directiva no tiene efecto. Esto te permite escribir componentes exclusivos del cliente que pueden ser utilizados simultáneamente desde componentes del servidor y del cliente. -* Todo el código en un archivo `'use client'`, así como cualquier módulo que importe (directa o indirectamente), formará parte del gráfico de módulos del cliente y debe ser enviado y ejecutado por el cliente para ser renderizado en el navegador. Para reducir el tamaño del paquete del cliente y aprovechar al máximo el servidor, mueve el estado (y las directivas `'use client'`) más abajo en el árbol cuando sea posible y pasa los componetes del servidor renderizados [como hijos](/learn/passing-props-to-a-component#passing-jsx-as-children) a los componentes del cliente. -* Debido a que las props se serializan a través de la barrera servidor-cliente, ten en cuenta que la colocación de estas directivas puede afectar a la cantidad de datos enviados al cliente; evita estructuras de datos más grandes de lo necesario. -* Componentes como `` que no utilizan características exclusivas ni del servidor ni del cliente, generalmente no deben ser marcados con `'use client'`. De esta manera, pueden renderizarse exclusivamente en el servidor cuando se utilizan desde un componente de servidor y se agregarán al paquete del cliente cuando se utilicen desde un componente del cliente. -* Las bibliotecas publicadas en npm deben incluir `'use client'` en los componentes de React exportados que puedan renderizarse con props serializables y que utilicen características exclusivas de React para el cliente, para permitir que esos componentes sean importados y renderizados por componentes de servidor. De lo contrario, los usuarios deberán envolver los componentes de la biblioteca en sus propios archivos con `'use client'`, lo que puede ser incómodo y evitar que la biblioteca mueva la lógica al servidor en un futuro. Al publicar archivos precompilados a npm, asegúrate de que los archivos fuente con `'use client'` terminen en un paquete marcado con `'use client'`, separado de cualquier paquete que contenga exportaciones que se puedan utilizar directamente en el servidor. -* Los componentes del cliente seguirán ejecutándose como parte del renderizado del lado del servidor (SSR) o en la generación de sitios estáticos en tiempo de compilación (SSG), que actúan como clientes para transformar la salida de renderización inicial de los componentes de React en HTML la cuál se puede renderizar antes de que se descarguen los paquetes de javascript. Pero, no pueden utilizar características exclusivas del servidor, como la lectura directa desde una base de datos. -* Las directivas como `'use client'` deben estar al comienzo del archivo, antes que cualquier importación u otro código (los comentarios arriba de las directivas están permitidos). Deben escribirse con comillas simples o dobles, no con comillas invertidas. (El formato de la directiva `'use xyz'` se asemeja un poco a la convención de nombres `useXyz()` de los Hooks, pero la similitud es coincidencia.) +Often in a React app, you'll leverage third-party libraries to handle common UI patterns or logic. -## Uso {/*usage*/} +These libraries may rely on component Hooks or client APIs. Third-party components that use any of the following React APIs must run on the client: +* [createContext](/reference/react/createContext) +* [`react`](/reference/react/hooks) and [`react-dom`](/reference/react-dom/hooks) Hooks, excluding [`use`](/reference/react/use) and [`useId`](/reference/react/useId) +* [forwardRef](/reference/react/forwardRef) +* [memo](/reference/react/memo) +* [startTransition](/reference/react/startTransition) +* If they use client APIs, ex. DOM insertion or native platform views - -Esta sección es un trabajo en progreso. +If these libraries have been updated to be compatible with React Server Components, then they will already include `'use client'` markers of their own, allowing you to use them directly from your Server Components. If a library hasn't been updated, or if a component needs props like event handlers that can only be specified on the client, you may need to add your own Client Component file in between the third-party Client Component and your Server Component where you'd like to use it. -Esta API puede ser utilizada en cualquier framework que soporte React Server Components. Puede encontrar documentación adicional desde ellos. -* [Next.js documentation](https://nextjs.org/docs/getting-started/react-essentials) -* Más próximamente - +[TODO]: <> (Troubleshooting - need use-cases) diff --git a/src/content/reference/react/use-server.md b/src/content/reference/react/use-server.md index 80c5304a6..094316e16 100644 --- a/src/content/reference/react/use-server.md +++ b/src/content/reference/react/use-server.md @@ -24,34 +24,191 @@ canary: true ### `'use server'` {/*use-server*/} -Añade `'use server';` en la parte superior de una función asíncrona para marcar que la función puede ser ejecutada por el cliente. +Add `'use server'` at the top of an async function body to mark the function as callable by the client. We call these functions _server actions_. -```js +```js {2} async function addToCart(data) { 'use server'; // ... } - -// ``` -Esta función puede ser pasada al cliente. Cuando es llamada en el cliente, hará una petición de red al servidor que incluye una copia serializada de cualquier argumento pasado. Si la función del servidor devuelve un valor, ese valor será serializado y devuelto al cliente. +When calling a server action on the client, it will make a network request to the server that includes a serialized copy of any arguments passed. If the server action returns a value, that value will be serialized and returned to the client. -Alternativamente, añade `'use server'` en la parte superior de un archivo para marcar todas las exportaciones dentro de ese archivo como funciones asíncronas del servidor que pueden ser usadas en cualquier lugar, incluso importadas en los archivos de componentes de cliente. +Instead of individually marking functions with `'use server'`, you can add the directive to the top of a file to mark all exports within that file as server actions that can be used anywhere, including imported in client code. -#### Advertencias {/*caveats*/} +#### Caveats {/*caveats*/} +* `'use server'` must be at the very beginning of their function or module; above any other code including imports (comments above directives are OK). They must be written with single or double quotes, not backticks. +* `'use server'` can only be used in server-side files. The resulting server actions can be passed to Client Components through props. See supported [types for serialization](#serializable-parameters-and-return-values). +* 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 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. -* Recuerda que los parámetros de las funciones marcadas con `'use server'` están totalmente controlados por el cliente. Por seguridad, trátalos siempre como entradas no confiables, asegurándote de validar y escapar los argumentos como sea apropiado. -* Para evitar la confusión que podría resultar de mezclar código del lado del cliente y del lado del servidor en el mismo archivo, `'use server'` sólo puede usarse en archivos del lado del servidor; las funciones resultantes pueden pasarse a componentes del cliente a través de _props_. -* Dado que las llamadas de red subyacentes son siempre asíncronas, `'use server'` sólo puede usarse en funciones asíncronas. -* Directivas como `'use server'` deben estar al principio de tu función o archivo, por encima de cualquier otro código incluyendo importaciones (los comentarios sobre las directivas están bien). Deben escribirse con comillas simples o dobles, no con comillas invertidas. (El formato de la directiva `'use xyz'` se parece un poco a la convención de nomenclatura del Hook `useXyz()`, pero el parecido es coincidencia). +### Security considerations {/*security*/} -## Uso {/*usage*/} +Arguments to server actions are fully client-controlled. For security, always treat them as untrusted input, and make sure to validate and escape arguments as appropriate. + +In any server action, make sure to validate that the logged-in user is allowed to perform that action. -Esta sección es un trabajo en progreso. - -Esta API puede ser utilizada en cualquier framework que soporte React Server Components. Puede encontrar documentación adicional desde ellos. -* [Next.js documentation](https://nextjs.org/docs/getting-started/react-essentials) -* Más próximamente + +To prevent sending sensitive data from a server action, there are experimental taint APIs to prevent unique values and objects from being passed to client code. + +See [experimental_taintUniqueValue](/reference/react/experimental_taintUniqueValue) and [experimental_taintObjectReference](/reference/react/experimental_taintObjectReference). + + +### Serializable arguments and return values {/*serializable-parameters-and-return-values*/} + +As client code calls the server action over the network, any arguments passed will need to be serializable. + +Here are supported types for server action arguments: + +* Primitives + * [string](https://developer.mozilla.org/en-US/docs/Glossary/String) + * [number](https://developer.mozilla.org/en-US/docs/Glossary/Number) + * [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) + * [boolean](https://developer.mozilla.org/en-US/docs/Glossary/Boolean) + * [undefined](https://developer.mozilla.org/en-US/docs/Glossary/Undefined) + * [null](https://developer.mozilla.org/en-US/docs/Glossary/Null) + * [symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol), only symbols registered in the global Symbol registry via [`Symbol.for`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for) +* Iterables containing serializable values + * [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) + * [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) + * [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) + * [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) + * [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) and [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) +* [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) +* [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) instances +* Plain [objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object): those created with [object initializers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer), with serializable properties +* Functions that are server actions +* [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) + +Notably, these are not supported: +* React elements, or [JSX](https://react.dev/learn/writing-markup-with-jsx) +* Functions, including component functions or any other function that is not a server action +* [Classes](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Classes_in_JavaScript) +* Objects that are instances of any class (other than the built-ins mentioned) or objects with [a null prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#null-prototype_objects) +* Symbols not registered globally, ex. `Symbol('my new symbol')` + + +Supported serializable return values are the same as [serializable props](/reference/react/use-client#passing-props-from-server-to-client-components) for a boundary Client Component. + + +## Uso {/*usage*/} + +### Server actions in forms {/*server-actions-in-forms*/} + +The most common use case of server actions will be calling server functions that mutate data. On the browser, the [HTML form element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) is the traditional approach for a user to submit a mutation. With React Server Components, React introduces first-class support for server actions in [forms](/reference/react-dom/components/form). + +Here is a form that allows a user to request a username. + +```js [[1, 3, "formData"]] +// App.js + +async function requestUsername(formData) { + 'use server'; + const username = formData.get('username'); + // ... +} + +export default App() { + + + +
+} +``` + +In this example `requestUsername` is a server action passed to a `
`. When a user submits this form, there is a network request to the server function `requestUsername`. When calling a server action in a form, React will supply the form's [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) as the first argument to the server action. + +By passing a server action to the form `action`, React can [progressively enhance](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement) the form. This means that forms can be submitted before the JavaScript bundle is loaded. + +#### Handling return values in forms {/*handling-return-values*/} + +In the username request form, there might be the chance that a username is not available. `requestUsername` should tell us if it fails or not. + +To update the UI based on the result of a server action while supporting progressive enhancement, use [`useFormState`](/reference/react-dom/hooks/useFormState). + +```js +// requestUsername.js +'use server'; + +export default async function requestUsername(formData) { + const username = formData.get('username'); + if (canRequest(username)) { + // ... + return 'successful'; + } + return 'failed'; +} +``` + +```js {4,8}, [[2, 2, "'use client'"]] +// UsernameForm.js +'use client'; + +import {useFormState} from 'react-dom'; +import requestUsername from './requestUsername'; + +function UsernameForm() { + const [returnValue, action] = useFormState(requestUsername, 'n/a'); + + return ( + <> + + + +
+

Last submission request returned: {returnValue}

+ + ); +} +``` + +Note that like most Hooks, `useFormState` can only be called in [client code](/reference/react/use-client). + +### Calling a server action outside of `
` {/*calling-a-server-action-outside-of-form*/} + +Server actions are exposed server endpoints and can be called anywhere in client code. + +When using a server action outside of a [form](/reference/react-dom/components/form), call the server action in a [transition](/reference/react/useTransition), which allows you to display a loading indicator, show [optimistic state updates](/reference/react/useOptimistic), and handle unexpected errors. Forms will automatically wrap server actions in transitions. + +```js {9-12} +import incrementLike from './actions'; +import { useState, useTransition } from 'react'; + +function LikeButton() { + const [isPending, startTransition] = useTransition(); + const [likeCount, setLikeCount] = useState(0); + + const onClick = () => { + startTransition(async () => { + const currentCount = await incrementLike(); + setLikeCount(currentCount); + }); + }; + + return ( + <> +

Total Likes: {likeCount}

+ ; + + ); +} +``` + +```js +// actions.js +'use server'; + +let likeCount = 0; +export default async incrementLike() { + likeCount++; + return likeCount; +} +``` + +To read a server action return value, you'll need to `await` the promise returned. diff --git a/src/sidebarReference.json b/src/sidebarReference.json index 40fabdf68..05366cc18 100644 --- a/src/sidebarReference.json +++ b/src/sidebarReference.json @@ -6,9 +6,13 @@ "hasSectionHeader": true, "sectionHeader": "react@18.2.0" }, + { + "title": "Overview", + "path": "/reference/react" + }, { "title": "Hooks", - "path": "/reference/react", + "path": "/reference/react/hooks", "routes": [ { "title": "use",