From 231be651fcfa39cbdb8967ae16f0e1d543f50047 Mon Sep 17 00:00:00 2001 From: Vicenciomf1 <101673305+Vicenciomf1@users.noreply.github.com> Date: Tue, 18 Jul 2023 04:42:35 -0400 Subject: [PATCH 001/131] Update you-might-not-need-an-effect.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Traducción del contenido - Falta la sección de challenges --- .../learn/you-might-not-need-an-effect.md | 294 +++++++++--------- 1 file changed, 147 insertions(+), 147 deletions(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index a3b33d3a7..2ffb72226 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -1,45 +1,45 @@ --- -title: 'You Might Not Need an Effect' +title: 'Quizá no necesites un Efecto' --- -Effects are an escape hatch from the React paradigm. They let you "step outside" of React and synchronize your components with some external system like a non-React widget, network, or the browser DOM. If there is no external system involved (for example, if you want to update a component's state when some props or state change), you shouldn't need an Effect. Removing unnecessary Effects will make your code easier to follow, faster to run, and less error-prone. +Los Efectos son una puerta de escape del paradigma de React. Te permiten "salir" de React y sincronizar tus componentes con algún sistema externo como un widget externo a React, una red o el DOM del navegador. Si no hay algún sistema externo involucrado (por ejemplo, si quieres actualizar el estado de un componente cuando algunas props o estados cambien), no deberías necesitar un Efecto. Eliminar los Efectos innecesarios hará que tu código sea más fácil de comprender, más rápido de ejecutar y menos propenso a errores. -* Why and how to remove unnecessary Effects from your components -* How to cache expensive computations without Effects -* How to reset and adjust component state without Effects -* How to share logic between event handlers -* Which logic should be moved to event handlers -* How to notify parent components about changes +* Por qué y cómo eliminar los Efectos innecesarios de tus componentes +* Cómo almacenar en caché cálculos costosos sin Efectos +* Cómo restablecer y ajustar el estado de los componentes sin Efectos +* Cómo compartir la lógica entre manejadores de eventos +* Qué lógica debe ser trasladada a los manejadores de eventos +* Cómo notificar a los componentes padre sobre cambios -## How to remove unnecessary Effects {/*how-to-remove-unnecessary-effects*/} +## Cómo eliminar Efectos innecesarios {/*how-to-remove-unnecessary-effects*/} -There are two common cases in which you don't need Effects: +Hay dos casos comunes en los que no necesitarás Efectos: -* **You don't need Effects to transform data for rendering.** For example, let's say you want to filter a list before displaying it. You might feel tempted to write an Effect that updates a state variable when the list changes. However, this is inefficient. When you update the state, React will first call your component functions to calculate what should be on the screen. Then React will ["commit"](/learn/render-and-commit) these changes to the DOM, updating the screen. Then React will run your Effects. If your Effect *also* immediately updates the state, this restarts the whole process from scratch! To avoid the unnecessary render passes, transform all the data at the top level of your components. That code will automatically re-run whenever your props or state change. -* **You don't need Effects to handle user events.** For example, let's say you want to send an `/api/buy` POST request and show a notification when the user buys a product. In the Buy button click event handler, you know exactly what happened. By the time an Effect runs, you don't know *what* the user did (for example, which button was clicked). This is why you'll usually handle user events in the corresponding event handlers. +* **No es necesario usar Efectos a la hora de transformar datos para su renderizado.** Por ejemplo, supongamos que quieres filtrar una lista antes de mostrarla. Podrías sentirte tentado a escribir un Efecto que actualice una variable de estado cuando la lista cambie. Sin embargo, esto no es eficiente. Ya que cuando actualices el estado de tu componente, React primero llamará a las funciones de tu componente para determinar lo que debe aparecer en la pantalla. Luego React ["confirmará"](/learn/render-and-commit) estos cambios en el DOM, actualizando la pantalla. Luego de ello React ejecutará tus Efectos. Si tu Efecto *también* actualiza inmediatamente el estado, ¡esto reiniciará todo el proceso desde cero! Para evitar renderizaciones innecesarias, transforma todos los datos en el nivel superior de tus componentes. Ese código se volverá a ejecutar automáticamente cada vez que tus props o tu estado cambien. +* **No necesitarás Efectos para manejar eventos de usuario.** Por ejemplo, digamos que quieres enviar una petición POST a `/api/buy` y mostrar una notificación cuando el usuario compra un producto. En el manejador de evento de clic del botón de compra, se sabe exactamente lo que ha pasado. En el momento en que se ejecuta un Efecto, no sabes *qué* hizo el usuario (por ejemplo, qué botón se pulsó). Es por esto que generalmente se manejan los eventos de usuario en sus respectivos manejadores de eventos. -You *do* need Effects to [synchronize](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) with external systems. For example, you can write an Effect that keeps a jQuery widget synchronized with the React state. You can also fetch data with Effects: for example, you can synchronize the search results with the current search query. Keep in mind that modern [frameworks](/learn/start-a-new-react-project#production-grade-react-frameworks) provide more efficient built-in data fetching mechanisms than writing Effects directly in your components. +Pero *sí* necesitarás Efectos para [sincronizar](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) tus componentes con sistemas externos. Por ejemplo, puedes escribir un Efecto que mantenga a un widget de jQuery sincronizado con el estado de React. También puedes cargar datos con Efectos: por ejemplo, puedes sincronizar los resultados de búsqueda con la consulta de búsqueda actual. Ten en cuenta que los [*frameworks*](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos de carga de datos incorporados mucho más eficientes que escribir Efectos directamente en tus componentes. -To help you gain the right intuition, let's look at some common concrete examples! +Para ayudarte a obtener una buena intuición, ¡veamos algunos ejemplos concretos comunes! -### Updating state based on props or state {/*updating-state-based-on-props-or-state*/} +### Actualizar un estado en relación a otras props o estados {/*updating-state-based-on-props-or-state*/} -Suppose you have a component with two state variables: `firstName` and `lastName`. You want to calculate a `fullName` from them by concatenating them. Moreover, you'd like `fullName` to update whenever `firstName` or `lastName` change. Your first instinct might be to add a `fullName` state variable and update it in an Effect: +Supongamos que tienes un componente con dos variables de estado: `firstName` para un nombre y `lastName` para un apellido. Y que quieres calcular un nombre completo como `fullName` a partir de la concatenación de los anteriores. Además, te gustaría que `fullName` se actualizara cada vez que `firstName` o `lastName` cambien. Tu primer impulso podría ser añadir una variable de estado `fullName` y actualizarla en un Efecto: ```js {5-9} function Form() { const [firstName, setFirstName] = useState('Taylor'); const [lastName, setLastName] = useState('Swift'); - // 🔴 Avoid: redundant state and unnecessary Effect + // 🔴 Desaconsejado: estado redundante y Efecto innecesario const [fullName, setFullName] = useState(''); useEffect(() => { setFullName(firstName + ' ' + lastName); @@ -48,29 +48,29 @@ function Form() { } ``` -This is more complicated than necessary. It is inefficient too: it does an entire render pass with a stale value for `fullName`, then immediately re-renders with the updated value. Remove the state variable and the Effect: +Esto es más complicado de lo necesario. También es ineficiente: desencadena un ciclo completo de renderizado con un valor antiguo para `fullName`, y luego inmediatamente vuelve a renderizar con el valor actualizado. Es mejor que elimines tanto la variable de estado como el efecto: ```js {4-5} function Form() { const [firstName, setFirstName] = useState('Taylor'); const [lastName, setLastName] = useState('Swift'); - // ✅ Good: calculated during rendering + // ✅ Buena práctica: calcularlo durante el renderizado const fullName = firstName + ' ' + lastName; // ... } ``` -**When something can be calculated from the existing props or state, [don't put it in state.](/learn/choosing-the-state-structure#avoid-redundant-state) Instead, calculate it during rendering.** This makes your code faster (you avoid the extra "cascading" updates), simpler (you remove some code), and less error-prone (you avoid bugs caused by different state variables getting out of sync with each other). If this approach feels new to you, [Thinking in React](/learn/thinking-in-react#step-3-find-the-minimal-but-complete-representation-of-ui-state) explains what should go into state. +**Cuando algo puede ser calculado a partir de las props o el estado existente, [no lo pongas en un nuevo estado.](/learn/choosing-the-state-structure#avoid-redundant-state) Es mejor calcularlo durante el renderizado.** Esta manera hace que tu código sea más rápido (evitas las actualizaciones extra "en cascada"), más simple (te ahorras algo de código), y menos propenso a errores (evitas errores causados por diferentes variables de estado que no están sincronizadas entre sí). Si este enfoque es nuevo para ti, [pensar en React](/learn/thinking-in-react#step-3-find-the-minimal-but-complete-representation-of-ui-state) tiene algunas orientaciones sobre lo que debería ir en el estado. -### Caching expensive calculations {/*caching-expensive-calculations*/} +### Almacenar en caché los cálculos costosos {/*caching-expensive-calculations*/} -This component computes `visibleTodos` by taking the `todos` it receives by props and filtering them according to the `filter` prop. You might feel tempted to store the result in state and update it from an Effect: +El objetivo del siguiente componente `TodoList` es mostrar una lista de tareas pendientes, en él tenemos el cálculo de las tareas pendientes a mostrar (`visibleTodos`) tomando las tareas (`todos`) que recibe por props, filtrándolas de acuerdo al filtro (`filter`) que también recibe por props. Podrías sentirte tentado a almacenar el resultado de este cálculo en una variable de estado y actualizarlo en un efecto: ```js {4-8} function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); - // 🔴 Avoid: redundant state and unnecessary Effect + // 🔴 Desaconsejado: : estado redundante y Efecto innecesario const [visibleTodos, setVisibleTodos] = useState([]); useEffect(() => { setVisibleTodos(getFilteredTodos(todos, filter)); @@ -80,20 +80,20 @@ function TodoList({ todos, filter }) { } ``` -Like in the earlier example, this is both unnecessary and inefficient. First, remove the state and the Effect: +Como en el ejemplo anterior, esto es innecesario e ineficiente. En primera instancia, elimina el estado y el Efecto: ```js {3-4} function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); - // ✅ This is fine if getFilteredTodos() is not slow. + // ✅ Esto está bien si getFilteredTodos() no es demasiado lento. const visibleTodos = getFilteredTodos(todos, filter); // ... } ``` -Usually, this code is fine! But maybe `getFilteredTodos()` is slow or you have a lot of `todos`. In that case you don't want to recalculate `getFilteredTodos()` if some unrelated state variable like `newTodo` has changed. +Por lo general, ¡este código está bien! Pero quizás `getFilteredTodos()` es lento o tienes muchos `todos`. En ese caso, no querrás volver a calcular `getFilteredTodos()` si alguna variable de estado no relacionada como `newTodo` ha cambiado. -You can cache (or ["memoize"](https://en.wikipedia.org/wiki/Memoization)) an expensive calculation by wrapping it in a [`useMemo`](/reference/react/useMemo) Hook: +Puedes almacenar en caché (o ["memoizar"](https://es.wikipedia.org/wiki/Memoización)) un cálculo costoso envolviéndolo en un Hook de React [`useMemo`](/reference/react/useMemo): ```js {5-8} import { useMemo, useState } from 'react'; @@ -101,35 +101,35 @@ import { useMemo, useState } from 'react'; function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); const visibleTodos = useMemo(() => { - // ✅ Does not re-run unless todos or filter change + // ✅ No se volverá a ejecutar a menos que todos o filter cambien return getFilteredTodos(todos, filter); }, [todos, filter]); // ... } ``` -Or, written as a single line: +O, escrito en una sola línea: ```js {5-6} import { useMemo, useState } from 'react'; function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); - // ✅ Does not re-run getFilteredTodos() unless todos or filter change + // ✅ No se volverá a ejecutar getFilteredTodos() a menos que todos o filter cambien const visibleTodos = useMemo(() => getFilteredTodos(todos, filter), [todos, filter]); // ... } ``` -**This tells React that you don't want the inner function to re-run unless either `todos` or `filter` have changed.** React will remember the return value of `getFilteredTodos()` during the initial render. During the next renders, it will check if `todos` or `filter` are different. If they're the same as last time, `useMemo` will return the last result it has stored. But if they are different, React will call the inner function again (and store its result). +**Esto le dice a React que no quieres que la función interna se vuelva a ejecutar a menos que `todos` o `filter` hayan cambiado.** React recordará el valor de retorno de `getFilteredTodos()` durante la renderización inicial. Durante los siguientes renderizados, verificará si `todos` o `filter` son diferentes. Si son los mismos que la última vez, `useMemo` devolverá el último resultado que ha almacenado. Pero si son diferentes, React llamará a la función interna nuevamente (y almacenará su resultado). -The function you wrap in [`useMemo`](/reference/react/useMemo) runs during rendering, so this only works for [pure calculations.](/learn/keeping-components-pure) +La función que envuelves en el Hook de React [`useMemo`](/reference/react/useMemo) se ejecuta durante el renderizado, por lo que solo funcionará para [cálculos puros.](/learn/keeping-components-pure) -#### How to tell if a calculation is expensive? {/*how-to-tell-if-a-calculation-is-expensive*/} +#### ¿Cómo saber si un cálculo es costoso? {/*how-to-tell-if-a-calculation-is-expensive*/} -In general, unless you're creating or looping over thousands of objects, it's probably not expensive. If you want to get more confidence, you can add a console log to measure the time spent in a piece of code: +En general, a menos que estés creando o iterando sobre miles de objetos, probablemente no sea costoso. Si quieres tener más confianza, puedes imprimirlo en la consola y medir el tiempo que pasa en ese fragmento de código: ```js {1,3} console.time('filter array'); @@ -137,33 +137,33 @@ const visibleTodos = getFilteredTodos(todos, filter); console.timeEnd('filter array'); ``` -Perform the interaction you're measuring (for example, typing into the input). You will then see logs like `filter array: 0.15ms` in your console. If the overall logged time adds up to a significant amount (say, `1ms` or more), it might make sense to memoize that calculation. As an experiment, you can then wrap the calculation in `useMemo` to verify whether the total logged time has decreased for that interaction or not: +Realiza la interacción que estás midiendo (por ejemplo, escribir en la entrada de texto). Luego verás registros como `filter array: 0.15ms` en tu consola. Si el tiempo total registrado suma una cantidad significativa (digamos, `1ms` o más), podría tener sentido memoizar ese cálculo. Como experimento, puedes envolver el cálculo en `useMemo` para verificar si el tiempo total registrado ha disminuido para esa interacción o no: ```js console.time('filter array'); const visibleTodos = useMemo(() => { - return getFilteredTodos(todos, filter); // Skipped if todos and filter haven't changed + return getFilteredTodos(todos, filter); // Se omite si todos y filter no han cambiado }, [todos, filter]); console.timeEnd('filter array'); ``` -`useMemo` won't make the *first* render faster. It only helps you skip unnecessary work on updates. +`useMemo` no hará que el *primer* renderizado sea más rápido. Solo te ayuda a evitar trabajo innecesario en las actualizaciones. -Keep in mind that your machine is probably faster than your users' so it's a good idea to test the performance with an artificial slowdown. For example, Chrome offers a [CPU Throttling](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) option for this. +Ten en cuenta que tu máquina probablemente sea más rápida que la de tus usuarios, por lo que es una buena idea probar el rendimiento con una ralentización artificial. Por ejemplo, Chrome ofrece una opción de [limitación de CPU](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) para esto. -Also note that measuring performance in development will not give you the most accurate results. (For example, when [Strict Mode](/reference/react/StrictMode) is on, you will see each component render twice rather than once.) To get the most accurate timings, build your app for production and test it on a device like your users have. +También ten en cuenta que medir el rendimiento en desarrollo no te dará los resultados más precisos. (Por ejemplo, cuando el "[Modo Estricto](/reference/react/StrictMode)" está activado, verás que cada componente se renderiza dos veces en lugar de una.) Para obtener los tiempos más precisos, compila tu aplicación para producción y pruébala en un dispositivo como el que tienen tus usuarios. -### Resetting all state when a prop changes {/*resetting-all-state-when-a-prop-changes*/} +### Reiniciar de cero el estado cuando una prop cambie {/*resetting-all-state-when-a-prop-changes*/} -This `ProfilePage` component receives a `userId` prop. The page contains a comment input, and you use a `comment` state variable to hold its value. One day, you notice a problem: when you navigate from one profile to another, the `comment` state does not get reset. As a result, it's easy to accidentally post a comment on a wrong user's profile. To fix the issue, you want to clear out the `comment` state variable whenever the `userId` changes: +Este componente `ProfilePage` recibe una prop `userId`. La página contiene una entrada de texto de comentario, y utiliza una variable de estado `comment` para guardar su valor. Un día, te das cuenta de un problema: cuando navegas de un perfil a otro, el estado `comment` no se reinicia. Como resultado, es fácil publicar accidentalmente un comentario en el perfil de un usuario incorrecto. Para solucionar el problema, quieres limpiar la variable de estado `comment` cada vez que el `userId` cambie: ```js {4-7} export default function ProfilePage({ userId }) { const [comment, setComment] = useState(''); - // 🔴 Avoid: Resetting state on prop change in an Effect + // 🔴 Desaconsejado: Reiniciar el estado según cambio de prop en un Efecto useEffect(() => { setComment(''); }, [userId]); @@ -171,9 +171,9 @@ export default function ProfilePage({ userId }) { } ``` -This is inefficient because `ProfilePage` and its children will first render with the stale value, and then render again. It is also complicated because you'd need to do this in *every* component that has some state inside `ProfilePage`. For example, if the comment UI is nested, you'd want to clear out nested comment state too. +Esto es ineficiente porque `ProfilePage` y sus hijos primero se renderizarán con el valor obsoleto, y luego se renderizarán de nuevo. También es complicado porque necesitarías hacer esto en *cada* componente que tenga algún estado dentro de `ProfilePage`. Por ejemplo, si la interfaz de usuario del comentario está anidada, también querrías limpiar el estado del comentario anidado. -Instead, you can tell React that each user's profile is conceptually a _different_ profile by giving it an explicit key. Split your component in two and pass a `key` attribute from the outer component to the inner one: +En lugar de ello, puedes decirle a React que cada perfil de usuario es conceptualmente un perfil _diferente_ dándole una _key_ explícita. Divide tu componente en dos y pasa un atributo `key` del componente exterior al interior: ```js {5,11-12} export default function ProfilePage({ userId }) { @@ -186,28 +186,28 @@ export default function ProfilePage({ userId }) { } function Profile({ userId }) { - // ✅ This and any other state below will reset on key change automatically + // ✅ Esto y cualquier otro estado a continuación se reiniciará automáticamente al cambiar la key const [comment, setComment] = useState(''); // ... } ``` -Normally, React preserves the state when the same component is rendered in the same spot. **By passing `userId` as a `key` to the `Profile` component, you're asking React to treat two `Profile` components with different `userId` as two different components that should not share any state.** Whenever the key (which you've set to `userId`) changes, React will recreate the DOM and [reset the state](/learn/preserving-and-resetting-state#option-2-resetting-state-with-a-key) of the `Profile` component and all of its children. Now the `comment` field will clear out automatically when navigating between profiles. +Usualmente, React conserva el estado cuando el mismo componente se renderiza en el mismo lugar. **Al pasar `userId` como una `key` al componente `Profile`, le estás pidiendo a React que trate a dos componentes `Profile` con diferentes `userId` como dos componentes diferentes que no deberían compartir ningún estado.** Cuando la key (que has establecido como `userId`) cambie, React recreará el DOM y [reiniciará el estado](/learn/preserving-and-resetting-state#option-2-resetting-state-with-a-key) del componente `Profile` y todos sus hijos. Ahora el campo `comment` se borrará automáticamente cuando se navegue entre perfiles. -Note that in this example, only the outer `ProfilePage` component is exported and visible to other files in the project. Components rendering `ProfilePage` don't need to pass the key to it: they pass `userId` as a regular prop. The fact `ProfilePage` passes it as a `key` to the inner `Profile` component is an implementation detail. +Ten en cuenta que en este ejemplo, solo el componente externo `ProfilePage` es exportado y visible para otros archivos en el proyecto. Los componentes que renderizan `ProfilePage` no necesitan pasar la key a este: pasan `userId` como una prop regular. El hecho de que `ProfilePage` lo pase como una `key` al componente interno `Profile` es un detalle de implementación. -### Adjusting some state when a prop changes {/*adjusting-some-state-when-a-prop-changes*/} +### Actualizar parte del estado cuando cambie una prop {/*adjusting-some-state-when-a-prop-changes*/} -Sometimes, you might want to reset or adjust a part of the state on a prop change, but not all of it. +A veces, querrás resetear o ajustar una parte del estado según un cambio de prop, pero no todo. -This `List` component receives a list of `items` as a prop, and maintains the selected item in the `selection` state variable. You want to reset the `selection` to `null` whenever the `items` prop receives a different array: +Este componente `List` recibe una lista de `items` como una prop y mantiene el elemento seleccionado en la variable de estado `selection`. Tu objetivo es resetear `selection` a `null` siempre que la prop `items` reciba un array diferente: ```js {5-8} function List({ items }) { const [isReverse, setIsReverse] = useState(false); const [selection, setSelection] = useState(null); - // 🔴 Avoid: Adjusting state on prop change in an Effect + // 🔴 Desaconsejado: Ajustar el estado según un cambio de prop en un Efecto useEffect(() => { setSelection(null); }, [items]); @@ -215,16 +215,16 @@ function List({ items }) { } ``` -This, too, is not ideal. Every time the `items` change, the `List` and its child components will render with a stale `selection` value at first. Then React will update the DOM and run the Effects. Finally, the `setSelection(null)` call will cause another re-render of the `List` and its child components, restarting this whole process again. +Esto tampoco es ideal. Debido a que cada vez que los `items` cambien, `List` y sus componentes hijos renderizarán con un valor `selection` obsoleto al comienzo. Luego React actualizará el DOM y ejecutará los Efectos. Finalmente, la llamada a `setSelection(null)` provocará otro renderizado de `List` y sus componentes hijos, nuevamente reiniciando por completo este proceso. -Start by deleting the Effect. Instead, adjust the state directly during rendering: +Comienza por eliminar el Efecto. En su lugar, ajusta el estado directamente durante el renderizado: ```js {5-11} function List({ items }) { const [isReverse, setIsReverse] = useState(false); const [selection, setSelection] = useState(null); - // Better: Adjust the state while rendering + // Una mejor práctica: Actualizar el estado al renderizar const [prevItems, setPrevItems] = useState(items); if (items !== prevItems) { setPrevItems(items); @@ -234,31 +234,31 @@ function List({ items }) { } ``` -[Storing information from previous renders](/reference/react/useState#storing-information-from-previous-renders) like this can be hard to understand, but it’s better than updating the same state in an Effect. In the above example, `setSelection` is called directly during a render. React will re-render the `List` *immediately* after it exits with a `return` statement. React has not rendered the `List` children or updated the DOM yet, so this lets the `List` children skip rendering the stale `selection` value. +[Almacenar información de renderizados anteriores](/reference/react/useState#storing-information-from-previous-renders) de esta manera puede ser difícil de entender, pero es mejor que actualizar el mismo estado en un Efecto. En el ejemplo anterior, `setSelection` se llama directamente durante un renderizado. React volverá a renderizar `List` *inmediatamente* después de su declaración `return`. React aún no ha renderizado los hijos de `List` ni ha actualizado el DOM, por lo que esto permite que los hijos de `List` omitan el renderizar el valor obsoleto de `selection`. -When you update a component during rendering, React throws away the returned JSX and immediately retries rendering. To avoid very slow cascading retries, React only lets you update the *same* component's state during a render. If you update another component's state during a render, you'll see an error. A condition like `items !== prevItems` is necessary to avoid loops. You may adjust state like this, but any other side effects (like changing the DOM or setting timeouts) should stay in event handlers or Effects to [keep components pure.](/learn/keeping-components-pure) +Cuando actualizas un componente durante el renderizado, React descarta el JSX devuelto e intenta inmediatamente el renderizado nuevamente. Para evitar reintentos en cascada muy lentos, React solo te permite actualizar el estado del *mismo* componente durante un renderizado. Si actualizas el estado de otro componente durante un renderizado, verás un error. Una condición como `items !== prevItems` es necesaria para evitar bucles. Puedes ajustar el estado de esta manera, pero cualquier otro efecto secundario (como cambiar el DOM o establecer timeouts) debe permanecer en manejadores de eventos o Efectos para [mantener a los componentes puros.](/learn/keeping-components-pure) -**Although this pattern is more efficient than an Effect, most components shouldn't need it either.** No matter how you do it, adjusting state based on props or other state makes your data flow more difficult to understand and debug. Always check whether you can [reset all state with a key](#resetting-all-state-when-a-prop-changes) or [calculate everything during rendering](#updating-state-based-on-props-or-state) instead. For example, instead of storing (and resetting) the selected *item*, you can store the selected *item ID:* +**Aunque este patrón es más eficiente que un Efecto, la mayoría de los componentes tampoco deberían necesitarlo.** No importa cómo lo hagas, ajustar el estado basado en las props u otro estado hace que tu flujo de datos sea más difícil de entender y depurar. Siempre verifica si puedes [resetear todo el estado con una key](#resetting-all-state-when-a-prop-changes) o [calcular todo durante el renderizado](#updating-state-based-on-props-or-state) en su lugar. Por ejemplo, en lugar de almacenar (y resetear) el *ítem* seleccionado, puedes almacenar el *ID del ítem seleccionado*: ```js {3-5} function List({ items }) { const [isReverse, setIsReverse] = useState(false); const [selectedId, setSelectedId] = useState(null); - // ✅ Best: Calculate everything during rendering + // ✅ Una mejor práctica: Calcular todo durante el renderizado const selection = items.find(item => item.id === selectedId) ?? null; // ... } ``` -Now there is no need to "adjust" the state at all. If the item with the selected ID is in the list, it remains selected. If it's not, the `selection` calculated during rendering will be `null` because no matching item was found. This behavior is different, but arguably better because most changes to `items` preserve the selection. +Ahora no hay necesidad de "ajustar" el estado en lo absoluto. Si el elemento con el ID seleccionado está en la lista, permanecerá seleccionado. Si no lo está, la `selection` calculada durante el renderizado será `null` porque no se encontró ningún elemento coincidente. Este comportamiento es diferente, pero se podría decir que es mejor porque la mayoría de los cambios en `items` preservan la selección. -### Sharing logic between event handlers {/*sharing-logic-between-event-handlers*/} +### Compartir la lógica entre manejadores de eventos {/*sharing-logic-between-event-handlers*/} -Let's say you have a product page with two buttons (Buy and Checkout) that both let you buy that product. You want to show a notification whenever the user puts the product in the cart. Calling `showNotification()` in both buttons' click handlers feels repetitive so you might be tempted to place this logic in an Effect: +Supongamos que tienes una página de producto con dos botones (Comprar y Pagar) los cuales te permiten comprar ese producto. Quieres mostrar una notificación cada vez que el usuario pone el producto en el carrito. Llamar a `showNotification()` en los manejadores de clic de ambos botones se siente repetitivo, por lo que podrías estar tentado a colocar esta lógica en un Efecto: ```js {2-7} function ProductPage({ product, addToCart }) { - // 🔴 Avoid: Event-specific logic inside an Effect + // 🔴 Evita: Lógica específica para evento dentro de un Efecto useEffect(() => { if (product.isInCart) { showNotification(`Added ${product.name} to the shopping cart!`); @@ -277,13 +277,13 @@ function ProductPage({ product, addToCart }) { } ``` -This Effect is unnecessary. It will also most likely cause bugs. For example, let's say that your app "remembers" the shopping cart between the page reloads. If you add a product to the cart once and refresh the page, the notification will appear again. It will keep appearing every time you refresh that product's page. This is because `product.isInCart` will already be `true` on the page load, so the Effect above will call `showNotification()`. +Este Efecto es innecesario. Incluso es muy probable que cause errores. Por ejemplo, digamos que tu aplicación "recuerda" el carrito de compras entre recargas de la página. Si añades un producto al carrito una vez y refrescas la página, la notificación aparecerá de nuevo. Y seguirá apareciendo cada vez que refresques la página del producto. Esto se debe a que `product.isInCart` ya será `true` en la carga de la página, por lo que el Efecto anterior llamará a `showNotification()`. -**When you're not sure whether some code should be in an Effect or in an event handler, ask yourself *why* this code needs to run. Use Effects only for code that should run *because* the component was displayed to the user.** In this example, the notification should appear because the user *pressed the button*, not because the page was displayed! Delete the Effect and put the shared logic into a function called from both event handlers: +**Cuando no estés seguro de si algún código debería estar en un Efecto o en un manejador de eventos, pregúntate *por qué* este código necesita ejecutarse. Usa Efectos solo para el código que debe ejecutarse *porque* el componente se mostró al usuario.** En este ejemplo, la notificación debería aparecer porque el usuario *presionó el botón*, ¡no porque se mostró la página! Elimina el Efecto y coloca la lógica compartida en una función llamada desde ambos manejadores de eventos: ```js {2-6,9,13} function ProductPage({ product, addToCart }) { - // ✅ Good: Event-specific logic is called from event handlers + // ✅ Buena práctica: La lógica específica para eventos se llama desde los manejadores de eventos function buyProduct() { addToCart(product); showNotification(`Added ${product.name} to the shopping cart!`); @@ -301,23 +301,23 @@ function ProductPage({ product, addToCart }) { } ``` -This both removes the unnecessary Effect and fixes the bug. +Esto tanto elimina el Efecto innecesario como corrige el error. -### Sending a POST request {/*sending-a-post-request*/} +### Realizar una petición POST {/*sending-a-post-request*/} -This `Form` component sends two kinds of POST requests. It sends an analytics event when it mounts. When you fill in the form and click the Submit button, it will send a POST request to the `/api/register` endpoint: +Este componente `Form` envía dos tipos de solicitudes POST. Envía un evento de analíticas cuando se monta. Por otra parte, cuando llenas el formulario y haces clic en el botón Enviar, enviará una solicitud POST al endpoint `/api/register`: ```js {5-8,10-16} function Form() { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); - // ✅ Good: This logic should run because the component was displayed + // ✅ Buena práctica: Esta lógica debe ejecutarse porque el componente se mostró al usuario useEffect(() => { post('/analytics/event', { eventName: 'visit_form' }); }, []); - // 🔴 Avoid: Event-specific logic inside an Effect + // 🔴 Evita: Lógica específica de evento dentro de un Efecto const [jsonToSubmit, setJsonToSubmit] = useState(null); useEffect(() => { if (jsonToSubmit !== null) { @@ -333,36 +333,36 @@ function Form() { } ``` -Let's apply the same criteria as in the example before. +Apliquemos el mismo criterio que en el ejemplo anterior. -The analytics POST request should remain in an Effect. This is because the _reason_ to send the analytics event is that the form was displayed. (It would fire twice in development, but [see here](/learn/synchronizing-with-effects#sending-analytics) for how to deal with that.) +La solicitud POST de analíticas debe permanecer en un Efecto. Esto es porque la _razón_ para enviar el evento de analíticas es que el formulario se mostró. (Se dispararía dos veces en desarrollo, pero [mira aquí](/learn/synchronizing-with-effects#sending-analytics) cómo lidiar con eso.) -However, the `/api/register` POST request is not caused by the form being _displayed_. You only want to send the request at one specific moment in time: when the user presses the button. It should only ever happen _on that particular interaction_. Delete the second Effect and move that POST request into the event handler: +Sin embargo, la solicitud POST a `/api/register` no es causada por el formulario siendo _mostrado al usuario_. Solo quieres enviar la solicitud en un momento específico en el tiempo: cuando el usuario presiona el botón. Solo debería ocurrir _en esa interacción en particular_. Elimina el segundo Efecto y mueve esa solicitud POST al manejador de eventos: ```js {12-13} function Form() { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); - // ✅ Good: This logic runs because the component was displayed + // ✅ Buena práctica: Esta lógica se ejecuta porque el componente se mostró al usuario useEffect(() => { post('/analytics/event', { eventName: 'visit_form' }); }, []); function handleSubmit(e) { e.preventDefault(); - // ✅ Good: Event-specific logic is in the event handler + // ✅ Buena práctica: La lógica para el evento se ejecuta en un manejador de eventos post('/api/register', { firstName, lastName }); } // ... } ``` -When you choose whether to put some logic into an event handler or an Effect, the main question you need to answer is _what kind of logic_ it is from the user's perspective. If this logic is caused by a particular interaction, keep it in the event handler. If it's caused by the user _seeing_ the component on the screen, keep it in the Effect. +Cuando estaás por decidir si poner alguna lógica en un manejador de eventos o un Efecto, la pregunta principal que debes responder es _qué tipo de lógica_ es desde la perspectiva del usuario. Si esta lógica es causada por una interacción en particular, mantenla en el manejador de eventos. Si es causada porque el usuario _ve_ el componente en la pantalla, mantenla en el Efecto. -### Chains of computations {/*chains-of-computations*/} +### Cadenas de cálculos {/*chains-of-computations*/} -Sometimes you might feel tempted to chain Effects that each adjust a piece of state based on other state: +A veces podrías sentirte tentado a encadenar Efectos que ajustan una pieza de estado basada en otro estado: ```js {7-29} function Game() { @@ -371,7 +371,7 @@ function Game() { const [round, setRound] = useState(1); const [isGameOver, setIsGameOver] = useState(false); - // 🔴 Avoid: Chains of Effects that adjust the state solely to trigger each other + // 🔴 Evitar: Cadenas de Efectos que ajustan el estado solo para activarse entre sí useEffect(() => { if (card !== null && card.gold) { setGoldCardCount(c => c + 1); @@ -406,13 +406,13 @@ function Game() { // ... ``` -There are two problems with this code. +Hay dos problemas con este código. -One problem is that it is very inefficient: the component (and its children) have to re-render between each `set` call in the chain. In the example above, in the worst case (`setCard` → render → `setGoldCardCount` → render → `setRound` → render → `setIsGameOver` → render) there are three unnecessary re-renders of the tree below. +Un problema es que es muy ineficiente: el componente (y sus hijos) tienen que volver a renderizarse entre cada llamada a un actualizador `set-` en la cadena. En el ejemplo anterior, en el peor de los casos (`setCard` → render → `setGoldCardCount` → render → `setRound` → render → `setIsGameOver` → render) hay tres renderizaciones innecesarias del árbol hacia debajo. -Even if it weren't slow, as your code evolves, you will run into cases where the "chain" you wrote doesn't fit the new requirements. Imagine you are adding a way to step through the history of the game moves. You'd do it by updating each state variable to a value from the past. However, setting the `card` state to a value from the past would trigger the Effect chain again and change the data you're showing. Such code is often rigid and fragile. +Incluso si no fuera lento, a medida que tu código evoluciona, te encontrarás con casos en los que la "cadena" que escribiste no se ajusta a los nuevos requisitos. Imagina que estás añadiendo una forma de repasar el historial de movimientos del juego. Lo harías actualizando cada variable de estado a un valor del pasado. Sin embargo, establecer el estado `card` a un valor del pasado desencadenaría de nuevo la cadena de Efectos y cambiaría los datos que estás mostrando. Este tipo de código es a menudo rígido y frágil. -In this case, it's better to calculate what you can during rendering, and adjust the state in the event handler: +En este caso, es mejor calcular lo que puedas durante la renderización, y ajustar el estado en el manejador de eventos: ```js {6-7,14-26} function Game() { @@ -420,7 +420,7 @@ function Game() { const [goldCardCount, setGoldCardCount] = useState(0); const [round, setRound] = useState(1); - // ✅ Calculate what you can during rendering + // ✅ Calcula lo que puedas durante la renderización const isGameOver = round > 5; function handlePlaceCard(nextCard) { @@ -428,7 +428,7 @@ function Game() { throw Error('Game already ended.'); } - // ✅ Calculate all the next state in the event handler + // ✅ Calcula todo el siguiente estado en el manejador de eventos setCard(nextCard); if (nextCard.gold) { if (goldCardCount <= 3) { @@ -446,21 +446,21 @@ function Game() { // ... ``` -This is a lot more efficient. Also, if you implement a way to view game history, now you will be able to set each state variable to a move from the past without triggering the Effect chain that adjusts every other value. If you need to reuse logic between several event handlers, you can [extract a function](#sharing-logic-between-event-handlers) and call it from those handlers. +Esto es mucho más eficiente. Además, si implementas una forma de ver el historial del juego, ahora podrás establecer cada variable de estado a un movimiento del pasado sin activar la cadena de Efectos que ajusta todos los demás valores. Si necesitas reutilizar la lógica entre varios manejadores de eventos, puedes [extraer una función](#sharing-logic-between-event-handlers) y llamarla desde esos manejadores. -Remember that inside event handlers, [state behaves like a snapshot.](/learn/state-as-a-snapshot) For example, even after you call `setRound(round + 1)`, the `round` variable will reflect the value at the time the user clicked the button. If you need to use the next value for calculations, define it manually like `const nextRound = round + 1`. +Recuerda que dentro de los manejadores de eventos, [el estado se comporta como una instantánea.](/learn/state-as-a-snapshot) Por ejemplo, incluso después de llamar a `setRound(round + 1)`, la variable `round` reflejará el valor en el momento en que el usuario hizo clic en el botón. Si necesitas usar el siguiente valor para cálculos, defínelo manualmente como `const nextRound = round + 1`. -In some cases, you *can't* calculate the next state directly in the event handler. For example, imagine a form with multiple dropdowns where the options of the next dropdown depend on the selected value of the previous dropdown. Then, a chain of Effects is appropriate because you are synchronizing with network. +En algunos casos, *no puedes* calcular el siguiente estado directamente en el manejador de eventos. Por ejemplo, imagina un formulario con múltiples desplegables donde las opciones del siguiente desplegable dependen del valor seleccionado del desplegable anterior. Entonces, una cadena de Efectos es apropiada porque estás sincronizando con la red. -### Initializing the application {/*initializing-the-application*/} +### Inicializar la aplicación {/*initializing-the-application*/} -Some logic should only run once when the app loads. +Algunas lógicas sólo deben ejecutarse una vez cuando se carga la aplicación. -You might be tempted to place it in an Effect in the top-level component: +Podrías estar tentado a colocarla en un Efecto en el componente de nivel superior: ```js {2-6} function App() { - // 🔴 Avoid: Effects with logic that should only ever run once + // 🔴 Evitar: Efectos con lógica que sólo debería ejecutarse una vez useEffect(() => { loadDataFromLocalStorage(); checkAuthToken(); @@ -469,9 +469,9 @@ function App() { } ``` -However, you'll quickly discover that it [runs twice in development.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) This can cause issues--for example, maybe it invalidates the authentication token because the function wasn't designed to be called twice. In general, your components should be resilient to being remounted. This includes your top-level `App` component. +Sin embargo, rápidamente descubrirás que [se ejecuta dos veces en desarrollo.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) Esto puede causar problemas: por ejemplo, quizás invalida el token de autenticación porque la función no fue diseñada para ser llamada dos veces. En general, tus componentes deberían ser resistentes a ser desmontados. Esto incluye tu componente `App` de nivel superior. -Although it may not ever get remounted in practice in production, following the same constraints in all components makes it easier to move and reuse code. If some logic must run *once per app load* rather than *once per component mount*, add a top-level variable to track whether it has already executed: +Aunque puede que nunca se desmonte en la práctica en producción, seguir las mismas restricciones en todos los componentes facilita mover y reutilizar el código. Si alguna lógica debe ejecutarse *una vez por carga de la aplicación* en lugar de *una vez por montaje del componente*, añade una variable de nivel superior para rastrear si ya se ha ejecutado: ```js {1,5-6,10} let didInit = false; @@ -480,7 +480,7 @@ function App() { useEffect(() => { if (!didInit) { didInit = true; - // ✅ Only runs once per app load + // ✅ Solo se ejecuta una vez por carga de la aplicación loadDataFromLocalStorage(); checkAuthToken(); } @@ -489,11 +489,11 @@ function App() { } ``` -You can also run it during module initialization and before the app renders: +También puedes ejecutarlo durante la inicialización del módulo y antes de que la aplicación se renderice: ```js {1,5} -if (typeof window !== 'undefined') { // Check if we're running in the browser. - // ✅ Only runs once per app load +if (typeof window !== 'undefined') { // Comprueba si estamos ejecutándolo en el navegador. + // ✅ Solo se ejecuta una vez por carga de la aplicación checkAuthToken(); loadDataFromLocalStorage(); } @@ -503,17 +503,17 @@ function App() { } ``` -Code at the top level runs once when your component is imported--even if it doesn't end up being rendered. To avoid slowdown or surprising behavior when importing arbitrary components, don't overuse this pattern. Keep app-wide initialization logic to root component modules like `App.js` or in your application's entry point. +El código en el nivel superior se ejecuta una vez cuando se importa tu componente, incluso si no termina siendo renderizado. Para evitar ralentizaciones o comportamientos inesperados al importar componentes arbitrarios, no abuses de este patrón. Mantén la lógica de inicialización de la aplicación en los módulos de componentes raíz como `App.js` o en el punto de entrada de tu aplicación. -### Notifying parent components about state changes {/*notifying-parent-components-about-state-changes*/} +### Notificar a los componentes padre sobre cambios de estado {/*notifying-parent-components-about-state-changes*/} -Let's say you're writing a `Toggle` component with an internal `isOn` state which can be either `true` or `false`. There are a few different ways to toggle it (by clicking or dragging). You want to notify the parent component whenever the `Toggle` internal state changes, so you expose an `onChange` event and call it from an Effect: +Digamos que estás escribiendo un componente `Toggle` con un estado interno `isOn` que puede ser `true` o `false`. Hay varias formas diferentes de cambiarlo (haciendo clic o arrastrando). Quieres notificar al componente padre cada vez que el estado interno de `Toggle` cambia, así que expones un evento `onChange` y lo llamas desde un Efecto: ```js {4-7} function Toggle({ onChange }) { const [isOn, setIsOn] = useState(false); - // 🔴 Avoid: The onChange handler runs too late + // 🔴 Evitar: El manejador onChange se ejecuta demasiado tarde useEffect(() => { onChange(isOn); }, [isOn, onChange]) @@ -534,16 +534,16 @@ function Toggle({ onChange }) { } ``` -Like earlier, this is not ideal. The `Toggle` updates its state first, and React updates the screen. Then React runs the Effect, which calls the `onChange` function passed from a parent component. Now the parent component will update its own state, starting another render pass. It would be better to do everything in a single pass. +Como antes, esto no es ideal. El `Toggle` actualiza su estado primero, y React actualiza la pantalla. Luego React ejecuta el Efecto, que llama a la función `onChange` pasada desde un componente padre. Ahora el componente padre actualizará su propio estado, iniciando otro proceso de renderizado. Sería mejor hacer todo en un solo paso. -Delete the Effect and instead update the state of *both* components within the same event handler: +Elimina el Efecto y en su lugar actualiza el estado de *ambos* componentes dentro del mismo manejador de eventos: ```js {5-7,11,16,18} function Toggle({ onChange }) { const [isOn, setIsOn] = useState(false); function updateToggle(nextIsOn) { - // ✅ Good: Perform all updates during the event that caused them + // ✅ Bien: Realiza todas las actualizaciones durante el evento que las causó setIsOn(nextIsOn); onChange(nextIsOn); } @@ -564,12 +564,12 @@ function Toggle({ onChange }) { } ``` -With this approach, both the `Toggle` component and its parent component update their state during the event. React [batches updates](/learn/queueing-a-series-of-state-updates) from different components together, so there will only be one render pass. +Con este enfoque, tanto el componente `Toggle` como su componente padre actualizan su estado durante el evento. React [agrupa las actualizaciones](/learn/queueing-a-series-of-state-updates) de diferentes componentes, por lo que sólo habrá un paso de renderizado. -You might also be able to remove the state altogether, and instead receive `isOn` from the parent component: +También podrías eliminar el estado por completo, y en su lugar recibir `isOn` del componente padre: ```js {1,2} -// ✅ Also good: the component is fully controlled by its parent +// ✅ También está bien: el componente está completamente controlado por su padre function Toggle({ isOn, onChange }) { function handleClick() { onChange(!isOn); @@ -587,11 +587,11 @@ function Toggle({ isOn, onChange }) { } ``` -["Lifting state up"](/learn/sharing-state-between-components) lets the parent component fully control the `Toggle` by toggling the parent's own state. This means the parent component will have to contain more logic, but there will be less state overall to worry about. Whenever you try to keep two different state variables synchronized, try lifting state up instead! +["Elevar el estado"](/learn/sharing-state-between-components) te permite que el componente padre controle completamente el `Toggle` cambiando el estado propio del padre. Esto significa que el componente padre tendrá que contener más lógica, pero habrá menos estado en general de qué preocuparse. ¡Cada vez que intentes mantener dos variables de estado diferentes sincronizadas, intenta elevar el estado en su lugar! -### Passing data to the parent {/*passing-data-to-the-parent*/} +### Pasar datos al componente padre {/*passing-data-to-the-parent*/} -This `Child` component fetches some data and then passes it to the `Parent` component in an Effect: +Este componente `Child` carga algunos datos y luego los pasa al componente `Parent` en un Efecto: ```js {9-14} function Parent() { @@ -602,7 +602,7 @@ function Parent() { function Child({ onFetched }) { const data = useSomeAPI(); - // 🔴 Avoid: Passing data to the parent in an Effect + // 🔴 Evitar: Pasar datos de hijo a padre en un Efecto useEffect(() => { if (data) { onFetched(data); @@ -612,13 +612,13 @@ function Child({ onFetched }) { } ``` -In React, data flows from the parent components to their children. When you see something wrong on the screen, you can trace where the information comes from by going up the component chain until you find which component passes the wrong prop or has the wrong state. When child components update the state of their parent components in Effects, the data flow becomes very difficult to trace. Since both the child and the parent need the same data, let the parent component fetch that data, and *pass it down* to the child instead: +En React, los datos fluyen de los componentes padres a sus hijos. Cuando ves algo incorrecto en la pantalla, puedes rastrear de dónde viene la información subiendo la cadena de componentes hasta que encuentres qué componente pasa la prop incorrecta o tiene el estado incorrecto. Cuando los componentes hijos actualizan el estado de sus componentes padres en Efectos, el flujo de datos se vuelve muy difícil de rastrear. Como tanto el hijo como el padre necesitan los mismos datos, deja que el componente padre recupere esos datos, y *pásalos hacia abajo* al hijo en su lugar: ```js {4-5} function Parent() { const data = useSomeAPI(); // ... - // ✅ Good: Passing data down to the child + // ✅ Buena práctica: Pasar los datos desde padres a hijos return ; } @@ -627,15 +627,15 @@ function Child({ data }) { } ``` -This is simpler and keeps the data flow predictable: the data flows down from the parent to the child. +Esto es más sencillo y mantiene el flujo de datos predecible: los datos fluyen hacia abajo desde el padre al hijo. -### Subscribing to an external store {/*subscribing-to-an-external-store*/} +### Suscribirse a una fuente de datos externa {/*subscribing-to-an-external-store*/} -Sometimes, your components may need to subscribe to some data outside of the React state. This data could be from a third-party library or a built-in browser API. Since this data can change without React's knowledge, you need to manually subscribe your components to it. This is often done with an Effect, for example: +A veces, tus componentes pueden necesitar suscribirse a algunos datos fuera del estado de React. Estos datos podrían provenir de una biblioteca de terceros o de una API incorporada en el navegador. Como estos datos pueden cambiar sin que React lo sepa, necesitas suscribir manualmente tus componentes a ellos. Esto se hace a menudo con un Efecto, por ejemplo: ```js {2-17} function useOnlineStatus() { - // Not ideal: Manual store subscription in an Effect + // No ideal: Suscripción manual en un Efecto const [isOnline, setIsOnline] = useState(true); useEffect(() => { function updateState() { @@ -660,9 +660,9 @@ function ChatIndicator() { } ``` -Here, the component subscribes to an external data store (in this case, the browser `navigator.onLine` API). Since this API does not exist on the server (so it can't be used for the initial HTML), initially the state is set to `true`. Whenever the value of that data store changes in the browser, the component updates its state. +Aquí, el componente se suscribe a una fuente de datos externa (en este caso, la API `navigator.onLine` del navegador). Dado que esta API no existe en el servidor (por lo que no puede usarse para el HTML inicial), inicialmente el estado se establece en `true`. Siempre que el valor de esa fuente de datos cambia en el navegador, el componente actualiza su estado. -Although it's common to use Effects for this, React has a purpose-built Hook for subscribing to an external store that is preferred instead. Delete the Effect and replace it with a call to [`useSyncExternalStore`](/reference/react/useSyncExternalStore): +Aunque es común usar Efectos para esto, React tiene un Hook diseñado específicamente para suscribirse a una fuente externa que se prefiere en su lugar. Elimina el Efecto y reemplázalo con una llamada al Hook de React [`useSyncExternalStore`](/reference/react/useSyncExternalStore): ```js {11-16} function subscribe(callback) { @@ -675,11 +675,11 @@ function subscribe(callback) { } function useOnlineStatus() { - // ✅ Good: Subscribing to an external store with a built-in Hook + // ✅ Buena práctica: Suscribirse a una fuente externa con un Hook integrado return useSyncExternalStore( - subscribe, // React won't resubscribe for as long as you pass the same function - () => navigator.onLine, // How to get the value on the client - () => true // How to get the value on the server + subscribe, // React no volverá a suscribirse mientras pases la misma función + () => navigator.onLine, // Acá va el cómo obtener el valor en el cliente + () => true // Acá va el cómo obtener el valor en el servidor ); } @@ -689,11 +689,11 @@ function ChatIndicator() { } ``` -This approach is less error-prone than manually syncing mutable data to React state with an Effect. Typically, you'll write a custom Hook like `useOnlineStatus()` above so that you don't need to repeat this code in the individual components. [Read more about subscribing to external stores from React components.](/reference/react/useSyncExternalStore) +Este enfoque es menos propenso a errores que sincronizar manualmente datos mutables al estado de React con un Efecto. Generalmente, escribirás un Hook personalizado como `useOnlineStatus()` anteriormente para que no debas repetir este código en los componentes individuales. [Lee más sobre cómo suscribirte a fuentes externas desde componentes de React.](/reference/react/useSyncExternalStore) -### Fetching data {/*fetching-data*/} +### Cargar datos {/*fetching-data*/} -Many apps use Effects to kick off data fetching. It is quite common to write a data fetching Effect like this: +Muchas aplicaciones usan Efectos para iniciar la carga de datos. Es bastante común escribir un Efecto de carga de datos como este: ```js {5-10} function SearchResults({ query }) { @@ -701,7 +701,7 @@ function SearchResults({ query }) { const [page, setPage] = useState(1); useEffect(() => { - // 🔴 Avoid: Fetching without cleanup logic + // 🔴 Evita: Obtener datos sin lógica de limpieza fetchResults(query, page).then(json => { setResults(json); }); @@ -714,15 +714,15 @@ function SearchResults({ query }) { } ``` -You *don't* need to move this fetch to an event handler. +No necesitas mover esta carga de datos a un manejador de eventos. -This might seem like a contradiction with the earlier examples where you needed to put the logic into the event handlers! However, consider that it's not *the typing event* that's the main reason to fetch. Search inputs are often prepopulated from the URL, and the user might navigate Back and Forward without touching the input. +Esto puede parecer una contradicción con los ejemplos anteriores donde necesitabas poner la lógica en los manejadores de eventos. Sin embargo, considera que no es *el evento de escritura* el que es la razón principal para cargar datos. Las entradas de búsqueda a menudo se pre-rellenan desde la URL, y el usuario puede navegar hacia atrás y hacia adelante sin tocar la entrada de texto. -It doesn't matter where `page` and `query` come from. While this component is visible, you want to keep `results` [synchronized](/learn/synchronizing-with-effects) with data from the network for the current `page` and `query`. This is why it's an Effect. +No importa de dónde vengan `page` y `query`. Mientras este componente sea visible, querrás mantener los `results` [sincronizados](/learn/synchronizing-with-effects) con los datos de la red para la `page` y `query` actuales. Por eso es un Efecto. -However, the code above has a bug. Imagine you type `"hello"` fast. Then the `query` will change from `"h"`, to `"he"`, `"hel"`, `"hell"`, and `"hello"`. This will kick off separate fetches, but there is no guarantee about which order the responses will arrive in. For example, the `"hell"` response may arrive *after* the `"hello"` response. Since it will call `setResults()` last, you will be displaying the wrong search results. This is called a ["race condition"](https://en.wikipedia.org/wiki/Race_condition): two different requests "raced" against each other and came in a different order than you expected. +Sin embargo, el código anterior tiene un error. Imagina que escribes "hola" rápidamente. Entonces la `query` cambiará de "h", a "ho", "hol", y "hola". Esto iniciará búsquedas separadas, pero no hay garantía sobre el orden en que llegarán las respuestas. Por ejemplo, la respuesta "hol" puede llegar *después* de la respuesta "hola". Como "hol" llamará a `setResults()` al final, estarás mostrando los resultados de búsqueda incorrectos. Esto se llama una ["condición de carrera"](https://es.wikipedia.org/wiki/Condición_de_carrera): dos solicitudes diferentes "compitieron" entre sí y llegaron en un orden diferente al que esperabas. -**To fix the race condition, you need to [add a cleanup function](/learn/synchronizing-with-effects#fetching-data) to ignore stale responses:** +**Para corregir la condición de carrera, tendrás que [agregar una función de limpieza](/learn/synchronizing-with-effects#fetching-data) para ignorar las respuestas obsoletas:** ```js {5,7,9,11-13} function SearchResults({ query }) { @@ -747,13 +747,13 @@ function SearchResults({ query }) { } ``` -This ensures that when your Effect fetches data, all responses except the last requested one will be ignored. +Esto asegura que cuando tu Efecto carga datos, todas las respuestas excepto la última solicitada serán ignoradas. -Handling race conditions is not the only difficulty with implementing data fetching. You might also want to think about caching responses (so that the user can click Back and see the previous screen instantly), how to fetch data on the server (so that the initial server-rendered HTML contains the fetched content instead of a spinner), and how to avoid network waterfalls (so that a child can fetch data without waiting for every parent). +Manejar las condiciones de carrera no es la única dificultad al implementar la carga de datos. También podrías querer pensar en almacenar en caché las respuestas (para que el usuario pueda hacer clic en "Atrás" y ver la pantalla anterior instantáneamente), en cómo obtener datos en el servidor (para que el HTML inicial renderizado por el servidor contenga el contenido obtenido en lugar de un spinner), y en cómo evitar cascadas de red (para que un hijo pueda cargar datos sin esperar a cada padre). -**These issues apply to any UI library, not just React. Solving them is not trivial, which is why modern [frameworks](/learn/start-a-new-react-project#production-grade-react-frameworks) provide more efficient built-in data fetching mechanisms than fetching data in Effects.** +**Estos problemas se aplican a cualquier biblioteca de interfaz de usuario, no solo a React. Resolverlos no es trivial, por lo que los [frameworks](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos de carga de datos integrados más eficientes que la carga de datos con Efectos.** -If you don't use a framework (and don't want to build your own) but would like to make data fetching from Effects more ergonomic, consider extracting your fetching logic into a custom Hook like in this example: +Si no usas un framework (y no quieres construir el tuyo propio) pero te gustaría hacer que la carga de datos desde Efectos sea más ergonómica, considera extraer tu lógica de obtención a un Hook personalizado como en el siguiente ejemplo: ```js {4} function SearchResults({ query }) { @@ -786,20 +786,20 @@ function useData(url) { } ``` -You'll likely also want to add some logic for error handling and to track whether the content is loading. You can build a Hook like this yourself or use one of the many solutions already available in the React ecosystem. **Although this alone won't be as efficient as using a framework's built-in data fetching mechanism, moving the data fetching logic into a custom Hook will make it easier to adopt an efficient data fetching strategy later.** +Probablemente también querrás agregar alguna lógica para el manejo de errores y para seguir si el contenido está cargando. Puedes construir un Hook como este tú mismo o utilizar una de las muchas soluciones ya disponibles en el ecosistema de React. **Aunque esto por sí solo no será tan eficiente como usar el mecanismo de carga de datos integrado de un marco, trasladar la lógica de carga de datos a un Hook personalizado facilitará la adopción de una estrategia de carga de datos eficiente más tarde.** -In general, whenever you have to resort to writing Effects, keep an eye out for when you can extract a piece of functionality into a custom Hook with a more declarative and purpose-built API like `useData` above. The fewer raw `useEffect` calls you have in your components, the easier you will find to maintain your application. +En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes extraer una pieza de funcionalidad a un Hook personalizado con una API más declarativa y diseñada específicamente como el `useData` anterior. Cuantas menos llamadas innecesarias a `useEffect` tengas en tus componentes, más fácil será el mantenimiento de tu aplicación. -- If you can calculate something during render, you don't need an Effect. -- To cache expensive calculations, add `useMemo` instead of `useEffect`. -- To reset the state of an entire component tree, pass a different `key` to it. -- To reset a particular bit of state in response to a prop change, set it during rendering. -- Code that runs because a component was *displayed* should be in Effects, the rest should be in events. -- If you need to update the state of several components, it's better to do it during a single event. -- Whenever you try to synchronize state variables in different components, consider lifting state up. -- You can fetch data with Effects, but you need to implement cleanup to avoid race conditions. +- Si puedes calcular algo durante el renderizado, no necesitas un Efecto. +- Para almacenar en caché cálculos costosos, utiliza `useMemo` en lugar de `useEffect`. +- Para restablecer el estado de un árbol de componentes completo, pásale una `key` diferente. +- Para restablecer una porción de estado en respuesta a un cambio de prop, configúralo durante el renderizado. +- El código que se ejecuta porque un componente se *mostró* al usuario debería estar en Efectos, el resto debería estar en eventos. +- Si necesitas actualizar el estado de varios componentes, es mejor hacerlo durante un solo evento. +- Siempre que intentes sincronizar variables de estado en diferentes componentes, considera elevar el estado. +- Puedes obtener datos con Efectos, pero necesitas implementar la lógica de limpieza para evitar las "condiciones de carrera". From 9752ccc89ebf7c913d18553a4a85e772815654d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:35:28 -0300 Subject: [PATCH 002/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 2ffb72226..181332335 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -1,5 +1,5 @@ --- -title: 'Quizá no necesites un Efecto' +title: 'Quizás no necesites un Efecto' --- From b8642150473b68bfd4958b58be9e0567805aa6ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:36:36 -0300 Subject: [PATCH 003/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 181332335..46df23759 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -4,7 +4,7 @@ title: 'Quizás no necesites un Efecto' -Los Efectos son una puerta de escape del paradigma de React. Te permiten "salir" de React y sincronizar tus componentes con algún sistema externo como un widget externo a React, una red o el DOM del navegador. Si no hay algún sistema externo involucrado (por ejemplo, si quieres actualizar el estado de un componente cuando algunas props o estados cambien), no deberías necesitar un Efecto. Eliminar los Efectos innecesarios hará que tu código sea más fácil de comprender, más rápido de ejecutar y menos propenso a errores. +Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" de React y sincronizar tus componentes con algún sistema externo, como un _widget_ que no es de React, una red o el DOM del navegador. Si no hay ningún sistema externo involucrado (por ejemplo, si deseas actualizar el estado de un componente cuando cambian ciertas _props_ o el estado), no deberías necesitar un Efecto. Eliminar Efectos innecesarios hará que tu código sea más fácil de seguir, se ejecute más rápido y sea menos propenso a errores. From af557cd31c0a8f1e421e3ee441ec2e6dc6b38831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:36:50 -0300 Subject: [PATCH 004/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 46df23759..7b8a3d989 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -602,7 +602,7 @@ function Parent() { function Child({ onFetched }) { const data = useSomeAPI(); - // 🔴 Evitar: Pasar datos de hijo a padre en un Efecto + // 🔴 Evitar: Pasar datos al padre en un Efecto useEffect(() => { if (data) { onFetched(data); From a5de22b02627cda1bc86bd904ae153e0a40361a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:37:06 -0300 Subject: [PATCH 005/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 7b8a3d989..03257f96b 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -10,7 +10,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d -* Por qué y cómo eliminar los Efectos innecesarios de tus componentes +* Por qué y cómo eliminar Efectos innecesarios de tus componentes. * Cómo almacenar en caché cálculos costosos sin Efectos * Cómo restablecer y ajustar el estado de los componentes sin Efectos * Cómo compartir la lógica entre manejadores de eventos From 7217eb3d384c7a8bccca0fe3b9be304bb9d27eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:37:33 -0300 Subject: [PATCH 006/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 03257f96b..b904ec840 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -12,7 +12,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d * Por qué y cómo eliminar Efectos innecesarios de tus componentes. * Cómo almacenar en caché cálculos costosos sin Efectos -* Cómo restablecer y ajustar el estado de los componentes sin Efectos +* Cómo restablecer y ajustar el estado del componente sin utilizar Efectos. * Cómo compartir la lógica entre manejadores de eventos * Qué lógica debe ser trasladada a los manejadores de eventos * Cómo notificar a los componentes padre sobre cambios From d329a7828188a73d613dad5bd49ce4d159ec853d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:37:47 -0300 Subject: [PATCH 007/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index b904ec840..4e314c7e5 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -13,7 +13,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d * Por qué y cómo eliminar Efectos innecesarios de tus componentes. * Cómo almacenar en caché cálculos costosos sin Efectos * Cómo restablecer y ajustar el estado del componente sin utilizar Efectos. -* Cómo compartir la lógica entre manejadores de eventos +* Cómo compartir lógica entre controladores de eventos. * Qué lógica debe ser trasladada a los manejadores de eventos * Cómo notificar a los componentes padre sobre cambios From e195e23c7c87f9b782682da80f09d04cdcf7dd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:38:59 -0300 Subject: [PATCH 008/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 4e314c7e5..46507435a 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -11,7 +11,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d * Por qué y cómo eliminar Efectos innecesarios de tus componentes. -* Cómo almacenar en caché cálculos costosos sin Efectos +* Cómo almacenar en caché cálculos costosos sin utilizar Efectos. * Cómo restablecer y ajustar el estado del componente sin utilizar Efectos. * Cómo compartir lógica entre controladores de eventos. * Qué lógica debe ser trasladada a los manejadores de eventos From deb350855f01a8e755bd9f5e0a9f11475c031e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:39:33 -0300 Subject: [PATCH 009/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 46507435a..550a0e9d0 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -14,7 +14,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d * Cómo almacenar en caché cálculos costosos sin utilizar Efectos. * Cómo restablecer y ajustar el estado del componente sin utilizar Efectos. * Cómo compartir lógica entre controladores de eventos. -* Qué lógica debe ser trasladada a los manejadores de eventos +* Qué lógica debería ser trasladada a los controladores de eventos. * Cómo notificar a los componentes padre sobre cambios From 63edabacd1244478ddb02fdb9b007ecea607343e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:42:29 -0300 Subject: [PATCH 010/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 550a0e9d0..beefac90e 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -15,7 +15,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d * Cómo restablecer y ajustar el estado del componente sin utilizar Efectos. * Cómo compartir lógica entre controladores de eventos. * Qué lógica debería ser trasladada a los controladores de eventos. -* Cómo notificar a los componentes padre sobre cambios +* Cómo notificar a los componentes padre acerca de cambios. From bd996153d3b3bed3c7afb1f71c5f84626f72a1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:43:02 -0300 Subject: [PATCH 011/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index beefac90e..19288b16f 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -21,7 +21,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d ## Cómo eliminar Efectos innecesarios {/*how-to-remove-unnecessary-effects*/} -Hay dos casos comunes en los que no necesitarás Efectos: +Hay dos casos comunes en los cuales no necesitas utilizar Efectos: * **No es necesario usar Efectos a la hora de transformar datos para su renderizado.** Por ejemplo, supongamos que quieres filtrar una lista antes de mostrarla. Podrías sentirte tentado a escribir un Efecto que actualice una variable de estado cuando la lista cambie. Sin embargo, esto no es eficiente. Ya que cuando actualices el estado de tu componente, React primero llamará a las funciones de tu componente para determinar lo que debe aparecer en la pantalla. Luego React ["confirmará"](/learn/render-and-commit) estos cambios en el DOM, actualizando la pantalla. Luego de ello React ejecutará tus Efectos. Si tu Efecto *también* actualiza inmediatamente el estado, ¡esto reiniciará todo el proceso desde cero! Para evitar renderizaciones innecesarias, transforma todos los datos en el nivel superior de tus componentes. Ese código se volverá a ejecutar automáticamente cada vez que tus props o tu estado cambien. * **No necesitarás Efectos para manejar eventos de usuario.** Por ejemplo, digamos que quieres enviar una petición POST a `/api/buy` y mostrar una notificación cuando el usuario compra un producto. En el manejador de evento de clic del botón de compra, se sabe exactamente lo que ha pasado. En el momento en que se ejecuta un Efecto, no sabes *qué* hizo el usuario (por ejemplo, qué botón se pulsó). Es por esto que generalmente se manejan los eventos de usuario en sus respectivos manejadores de eventos. From 9ce590fca46ae45fe6f3fad30bc1e4a3df394647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:43:31 -0300 Subject: [PATCH 012/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 19288b16f..5d64055d5 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -23,7 +23,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d Hay dos casos comunes en los cuales no necesitas utilizar Efectos: -* **No es necesario usar Efectos a la hora de transformar datos para su renderizado.** Por ejemplo, supongamos que quieres filtrar una lista antes de mostrarla. Podrías sentirte tentado a escribir un Efecto que actualice una variable de estado cuando la lista cambie. Sin embargo, esto no es eficiente. Ya que cuando actualices el estado de tu componente, React primero llamará a las funciones de tu componente para determinar lo que debe aparecer en la pantalla. Luego React ["confirmará"](/learn/render-and-commit) estos cambios en el DOM, actualizando la pantalla. Luego de ello React ejecutará tus Efectos. Si tu Efecto *también* actualiza inmediatamente el estado, ¡esto reiniciará todo el proceso desde cero! Para evitar renderizaciones innecesarias, transforma todos los datos en el nivel superior de tus componentes. Ese código se volverá a ejecutar automáticamente cada vez que tus props o tu estado cambien. +* **No necesitas Efectos para transformar datos antes de renderizar.** Por ejemplo, supongamos que deseas filtrar una lista antes de mostrarla. Podrías sentirte tentado/a a escribir un Efecto que actualice una variable de estado cuando cambie la lista. Sin embargo, esto es ineficiente. Cuando actualizas el estado, React primero llama a las funciones de tu componente para calcular lo que debería mostrarse en la pantalla. Luego, React ["confirmará"](/learn/render-and-commit) estos cambios en el DOM, actualizando la pantalla. Después, React ejecuta tus Efectos. ¡Si tu Efecto también actualiza inmediatamente el estado, esto reinicia todo el proceso desde cero! Para evitar pasadas de renderizado innecesarias, transforma todos los datos en el nivel superior de tus componentes. Ese código se volverá a ejecutar automáticamente cada vez que tus _props_ o estado cambien. * **No necesitarás Efectos para manejar eventos de usuario.** Por ejemplo, digamos que quieres enviar una petición POST a `/api/buy` y mostrar una notificación cuando el usuario compra un producto. En el manejador de evento de clic del botón de compra, se sabe exactamente lo que ha pasado. En el momento en que se ejecuta un Efecto, no sabes *qué* hizo el usuario (por ejemplo, qué botón se pulsó). Es por esto que generalmente se manejan los eventos de usuario en sus respectivos manejadores de eventos. Pero *sí* necesitarás Efectos para [sincronizar](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) tus componentes con sistemas externos. Por ejemplo, puedes escribir un Efecto que mantenga a un widget de jQuery sincronizado con el estado de React. También puedes cargar datos con Efectos: por ejemplo, puedes sincronizar los resultados de búsqueda con la consulta de búsqueda actual. Ten en cuenta que los [*frameworks*](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos de carga de datos incorporados mucho más eficientes que escribir Efectos directamente en tus componentes. From adcd7126fcf9e6d7f710ca4cc1d8ff114c006a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:44:15 -0300 Subject: [PATCH 013/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 5d64055d5..18432a9ef 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -24,7 +24,7 @@ Los Efectos son una vía de escape del paradigma de React. Te permiten "salir" d Hay dos casos comunes en los cuales no necesitas utilizar Efectos: * **No necesitas Efectos para transformar datos antes de renderizar.** Por ejemplo, supongamos que deseas filtrar una lista antes de mostrarla. Podrías sentirte tentado/a a escribir un Efecto que actualice una variable de estado cuando cambie la lista. Sin embargo, esto es ineficiente. Cuando actualizas el estado, React primero llama a las funciones de tu componente para calcular lo que debería mostrarse en la pantalla. Luego, React ["confirmará"](/learn/render-and-commit) estos cambios en el DOM, actualizando la pantalla. Después, React ejecuta tus Efectos. ¡Si tu Efecto también actualiza inmediatamente el estado, esto reinicia todo el proceso desde cero! Para evitar pasadas de renderizado innecesarias, transforma todos los datos en el nivel superior de tus componentes. Ese código se volverá a ejecutar automáticamente cada vez que tus _props_ o estado cambien. -* **No necesitarás Efectos para manejar eventos de usuario.** Por ejemplo, digamos que quieres enviar una petición POST a `/api/buy` y mostrar una notificación cuando el usuario compra un producto. En el manejador de evento de clic del botón de compra, se sabe exactamente lo que ha pasado. En el momento en que se ejecuta un Efecto, no sabes *qué* hizo el usuario (por ejemplo, qué botón se pulsó). Es por esto que generalmente se manejan los eventos de usuario en sus respectivos manejadores de eventos. +* **No necesitas Efectos para manejar eventos del usuario.** Por ejemplo, supongamos que deseas enviar una solicitud POST `/api/buy` y mostrar una notificación cuando el usuario compra un producto. En el controlador de eventos del botón "Comprar", sabes exactamente lo que sucedió. Para el momento en que se ejecuta un Efecto, no sabes *qué* hizo el usuario (por ejemplo, qué botón se hizo clic). Por esta razón, generalmente se manejan los eventos del usuario en los controladores de eventos correspondientes. Pero *sí* necesitarás Efectos para [sincronizar](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) tus componentes con sistemas externos. Por ejemplo, puedes escribir un Efecto que mantenga a un widget de jQuery sincronizado con el estado de React. También puedes cargar datos con Efectos: por ejemplo, puedes sincronizar los resultados de búsqueda con la consulta de búsqueda actual. Ten en cuenta que los [*frameworks*](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos de carga de datos incorporados mucho más eficientes que escribir Efectos directamente en tus componentes. From 813738c6cb1f37c186602a1fab636fd3ef0e0759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:44:58 -0300 Subject: [PATCH 014/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 18432a9ef..63c77e148 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -26,7 +26,7 @@ Hay dos casos comunes en los cuales no necesitas utilizar Efectos: * **No necesitas Efectos para transformar datos antes de renderizar.** Por ejemplo, supongamos que deseas filtrar una lista antes de mostrarla. Podrías sentirte tentado/a a escribir un Efecto que actualice una variable de estado cuando cambie la lista. Sin embargo, esto es ineficiente. Cuando actualizas el estado, React primero llama a las funciones de tu componente para calcular lo que debería mostrarse en la pantalla. Luego, React ["confirmará"](/learn/render-and-commit) estos cambios en el DOM, actualizando la pantalla. Después, React ejecuta tus Efectos. ¡Si tu Efecto también actualiza inmediatamente el estado, esto reinicia todo el proceso desde cero! Para evitar pasadas de renderizado innecesarias, transforma todos los datos en el nivel superior de tus componentes. Ese código se volverá a ejecutar automáticamente cada vez que tus _props_ o estado cambien. * **No necesitas Efectos para manejar eventos del usuario.** Por ejemplo, supongamos que deseas enviar una solicitud POST `/api/buy` y mostrar una notificación cuando el usuario compra un producto. En el controlador de eventos del botón "Comprar", sabes exactamente lo que sucedió. Para el momento en que se ejecuta un Efecto, no sabes *qué* hizo el usuario (por ejemplo, qué botón se hizo clic). Por esta razón, generalmente se manejan los eventos del usuario en los controladores de eventos correspondientes. -Pero *sí* necesitarás Efectos para [sincronizar](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) tus componentes con sistemas externos. Por ejemplo, puedes escribir un Efecto que mantenga a un widget de jQuery sincronizado con el estado de React. También puedes cargar datos con Efectos: por ejemplo, puedes sincronizar los resultados de búsqueda con la consulta de búsqueda actual. Ten en cuenta que los [*frameworks*](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos de carga de datos incorporados mucho más eficientes que escribir Efectos directamente en tus componentes. +Es *cierto* que necesitas Efectos para [sincronizar](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) con sistemas externos. Por ejemplo, puedes escribir un Efecto que mantenga sincronizado un _widget_ de jQuery con el estado de React. También puedes obtener datos con Efectos, por ejemplo, puedes sincronizar los resultados de búsqueda con la consulta de búsqueda actual. Ten en cuenta que los [_frameworks_](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos más eficientes y nativos para obtener datos que escribir Efectos directamente en tus componentes. Para ayudarte a obtener una buena intuición, ¡veamos algunos ejemplos concretos comunes! From bceb58d364c91194ef677b807f28a6add80bdb0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:45:40 -0300 Subject: [PATCH 015/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 63c77e148..30bfd4b57 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -28,7 +28,7 @@ Hay dos casos comunes en los cuales no necesitas utilizar Efectos: Es *cierto* que necesitas Efectos para [sincronizar](/learn/synchronizing-with-effects#what-are-effects-and-how-are-they-different-from-events) con sistemas externos. Por ejemplo, puedes escribir un Efecto que mantenga sincronizado un _widget_ de jQuery con el estado de React. También puedes obtener datos con Efectos, por ejemplo, puedes sincronizar los resultados de búsqueda con la consulta de búsqueda actual. Ten en cuenta que los [_frameworks_](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos más eficientes y nativos para obtener datos que escribir Efectos directamente en tus componentes. -Para ayudarte a obtener una buena intuición, ¡veamos algunos ejemplos concretos comunes! +Para ayudarte a desarrollar la intuición adecuada, ¡veamos algunos ejemplos concretos comunes! ### Actualizar un estado en relación a otras props o estados {/*updating-state-based-on-props-or-state*/} From 1d75db0603642d1ac7a8611609816295f18eb89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:46:33 -0300 Subject: [PATCH 016/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 30bfd4b57..ca7a01006 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -30,7 +30,7 @@ Es *cierto* que necesitas Efectos para [sincronizar](/learn/synchronizing-with-e Para ayudarte a desarrollar la intuición adecuada, ¡veamos algunos ejemplos concretos comunes! -### Actualizar un estado en relación a otras props o estados {/*updating-state-based-on-props-or-state*/} +### Actualización del estado basada en _props_ o estado {/*updating-state-based-on-props-or-state*/} Supongamos que tienes un componente con dos variables de estado: `firstName` para un nombre y `lastName` para un apellido. Y que quieres calcular un nombre completo como `fullName` a partir de la concatenación de los anteriores. Además, te gustaría que `fullName` se actualizara cada vez que `firstName` o `lastName` cambien. Tu primer impulso podría ser añadir una variable de estado `fullName` y actualizarla en un Efecto: From b3b34869a3c9f100cce46c28dd95bf72b81a227b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:47:58 -0300 Subject: [PATCH 017/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index ca7a01006..dcd570503 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -64,7 +64,7 @@ function Form() { ### Almacenar en caché los cálculos costosos {/*caching-expensive-calculations*/} -El objetivo del siguiente componente `TodoList` es mostrar una lista de tareas pendientes, en él tenemos el cálculo de las tareas pendientes a mostrar (`visibleTodos`) tomando las tareas (`todos`) que recibe por props, filtrándolas de acuerdo al filtro (`filter`) que también recibe por props. Podrías sentirte tentado a almacenar el resultado de este cálculo en una variable de estado y actualizarlo en un efecto: +Este componente calcula `visibleTodos` tomando los `todos` que recibe a través de _props_ y filtrándolos según la _prop_ `filter`. Podrías sentirte tentado/a de almacenar el resultado en el estado y actualizarlo desde un Efecto: ```js {4-8} function TodoList({ todos, filter }) { From 3f761f842e609d72fa9bbb8fae022e8fd5572fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:48:36 -0300 Subject: [PATCH 018/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index dcd570503..7304943b2 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -799,7 +799,7 @@ En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes - El código que se ejecuta porque un componente se *mostró* al usuario debería estar en Efectos, el resto debería estar en eventos. - Si necesitas actualizar el estado de varios componentes, es mejor hacerlo durante un solo evento. - Siempre que intentes sincronizar variables de estado en diferentes componentes, considera elevar el estado. -- Puedes obtener datos con Efectos, pero necesitas implementar la lógica de limpieza para evitar las "condiciones de carrera". +- Puedes obtener datos con Efectos, pero necesitas implementar limpieza para evitar condiciones de carrera. From 5a18e763f368c400e3a578dfec234d3e0c9995c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:48:52 -0300 Subject: [PATCH 019/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 7304943b2..6832c4aaf 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -70,7 +70,7 @@ Este componente calcula `visibleTodos` tomando los `todos` que recibe a través function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); - // 🔴 Desaconsejado: : estado redundante y Efecto innecesario + // 🔴 Evitar: estado redundante y Efecto innecesario const [visibleTodos, setVisibleTodos] = useState([]); useEffect(() => { setVisibleTodos(getFilteredTodos(todos, filter)); From 45a449ce928e85c847bcac0f6f4c4b7f90e3f030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:49:03 -0300 Subject: [PATCH 020/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 6832c4aaf..d49b2d5b0 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -80,7 +80,7 @@ function TodoList({ todos, filter }) { } ``` -Como en el ejemplo anterior, esto es innecesario e ineficiente. En primera instancia, elimina el estado y el Efecto: +Al igual que en el ejemplo anterior, esto es innecesario e ineficiente. Primero, elimina el estado y el Efecto: ```js {3-4} function TodoList({ todos, filter }) { From 7a04a5d68d328b8e4c17eb14e8ccf9c0afcd3955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:49:14 -0300 Subject: [PATCH 021/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index d49b2d5b0..a1ba320a0 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -85,7 +85,7 @@ Al igual que en el ejemplo anterior, esto es innecesario e ineficiente. Primero, ```js {3-4} function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); - // ✅ Esto está bien si getFilteredTodos() no es demasiado lento. + // ✅ Esto está bien si getFilteredTodos() no es lento. const visibleTodos = getFilteredTodos(todos, filter); // ... } From c5da61c81f77e2ee3b0b6f82c812fb563fc82fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:49:26 -0300 Subject: [PATCH 022/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index a1ba320a0..de006024f 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -91,7 +91,7 @@ function TodoList({ todos, filter }) { } ``` -Por lo general, ¡este código está bien! Pero quizás `getFilteredTodos()` es lento o tienes muchos `todos`. En ese caso, no querrás volver a calcular `getFilteredTodos()` si alguna variable de estado no relacionada como `newTodo` ha cambiado. +Usualmente, ¡este código está bien! Pero tal vez `getFilteredTodos()` sea lento o tengas muchos `todos`. En ese caso, no querrás recalcular `getFilteredTodos()` si alguna variable de estado no relacionada, como `newTodo`, ha cambiado. Puedes almacenar en caché (o ["memoizar"](https://es.wikipedia.org/wiki/Memoización)) un cálculo costoso envolviéndolo en un Hook de React [`useMemo`](/reference/react/useMemo): From c0a31f679b158caa04ee44acda3df92aa19377c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:49:45 -0300 Subject: [PATCH 023/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index de006024f..e1a81b12b 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -32,7 +32,7 @@ Para ayudarte a desarrollar la intuición adecuada, ¡veamos algunos ejemplos co ### Actualización del estado basada en _props_ o estado {/*updating-state-based-on-props-or-state*/} -Supongamos que tienes un componente con dos variables de estado: `firstName` para un nombre y `lastName` para un apellido. Y que quieres calcular un nombre completo como `fullName` a partir de la concatenación de los anteriores. Además, te gustaría que `fullName` se actualizara cada vez que `firstName` o `lastName` cambien. Tu primer impulso podría ser añadir una variable de estado `fullName` y actualizarla en un Efecto: +Supongamos que tienes un componente con dos variables de estado: `firstName` y `lastName`. Deseas calcular un `fullName` a partir de ellos concatenándolos. Además, te gustaría que `fullName` se actualice cada vez que `firstName` o `lastName` cambien. Tu primer instinto podría ser agregar una variable de estado `fullName` y actualizarla en un Efecto: ```js {5-9} function Form() { From d1db3945b039668ba349fe50c78954530432285c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:50:00 -0300 Subject: [PATCH 024/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index e1a81b12b..c523c2380 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -115,7 +115,7 @@ import { useMemo, useState } from 'react'; function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); - // ✅ No se volverá a ejecutar getFilteredTodos() a menos que todos o filter cambien + // ✅ No se vuelve a ejecutar getFilteredTodos() a menos que cambien todos o filter. const visibleTodos = useMemo(() => getFilteredTodos(todos, filter), [todos, filter]); // ... } From 62ece0448fa304d079004cfe58f76c7dbe47631b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:50:13 -0300 Subject: [PATCH 025/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index c523c2380..43920e065 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -121,7 +121,7 @@ function TodoList({ todos, filter }) { } ``` -**Esto le dice a React que no quieres que la función interna se vuelva a ejecutar a menos que `todos` o `filter` hayan cambiado.** React recordará el valor de retorno de `getFilteredTodos()` durante la renderización inicial. Durante los siguientes renderizados, verificará si `todos` o `filter` son diferentes. Si son los mismos que la última vez, `useMemo` devolverá el último resultado que ha almacenado. Pero si son diferentes, React llamará a la función interna nuevamente (y almacenará su resultado). +**Esto le indica a React que no deseas que la función interna se vuelva a ejecutar a menos que `todos` o `filter` hayan cambiado.** React recordará el valor de retorno de `getFilteredTodos()` durante el renderizado inicial. Durante los siguientes renderizados, verificará si `todos` o `filter` son diferentes. Si son iguales que la última vez, `useMemo` devolverá el último resultado almacenado. Pero si son diferentes, React llamará nuevamente a la función interna (y almacenará su resultado). La función que envuelves en el Hook de React [`useMemo`](/reference/react/useMemo) se ejecuta durante el renderizado, por lo que solo funcionará para [cálculos puros.](/learn/keeping-components-pure) From 6f831df89386917971c32ffd220b9eae6e8e4f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:50:25 -0300 Subject: [PATCH 026/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 43920e065..82a1172ab 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -137,7 +137,7 @@ const visibleTodos = getFilteredTodos(todos, filter); console.timeEnd('filter array'); ``` -Realiza la interacción que estás midiendo (por ejemplo, escribir en la entrada de texto). Luego verás registros como `filter array: 0.15ms` en tu consola. Si el tiempo total registrado suma una cantidad significativa (digamos, `1ms` o más), podría tener sentido memoizar ese cálculo. Como experimento, puedes envolver el cálculo en `useMemo` para verificar si el tiempo total registrado ha disminuido para esa interacción o no: +Realiza la interacción que estás midiendo (por ejemplo, escribir en el campo de entrada (_input_)). Luego, verás registros en la consola como `filter array: 0.15ms`. Si el tiempo total registrado suma una cantidad significativa (digamos, `1ms` o más), podría tener sentido memoizar ese cálculo. Como experimento, puedes envolver el cálculo en `useMemo` para verificar si el tiempo total registrado ha disminuido para esa interacción o no: ```js console.time('filter array'); From 2be2e9b570b6419ae0135499ac98c5ce0718bf9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:50:39 -0300 Subject: [PATCH 027/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 82a1172ab..7301c2716 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -151,7 +151,7 @@ console.timeEnd('filter array'); Ten en cuenta que tu máquina probablemente sea más rápida que la de tus usuarios, por lo que es una buena idea probar el rendimiento con una ralentización artificial. Por ejemplo, Chrome ofrece una opción de [limitación de CPU](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) para esto. -También ten en cuenta que medir el rendimiento en desarrollo no te dará los resultados más precisos. (Por ejemplo, cuando el "[Modo Estricto](/reference/react/StrictMode)" está activado, verás que cada componente se renderiza dos veces en lugar de una.) Para obtener los tiempos más precisos, compila tu aplicación para producción y pruébala en un dispositivo como el que tienen tus usuarios. +También ten en cuenta que medir el rendimiento en desarrollo no te dará los resultados más precisos. (Por ejemplo, cuando [Modo Estricto](/reference/react/StrictMode) está activado, verás que cada componente se renderiza dos veces en lugar de una). Para obtener los tiempos más precisos, construye tu aplicación para producción y pruébala en un dispositivo similar al que usan tus usuarios. From 7baada4b53cc32febbf173bb22d804da08e8fbdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:50:50 -0300 Subject: [PATCH 028/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 7301c2716..1125b437c 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -155,7 +155,7 @@ También ten en cuenta que medir el rendimiento en desarrollo no te dará los re -### Reiniciar de cero el estado cuando una prop cambie {/*resetting-all-state-when-a-prop-changes*/} +### Restablecer todo el estado cuando una _prop_ cambia {/*resetting-all-state-when-a-prop-changes*/} Este componente `ProfilePage` recibe una prop `userId`. La página contiene una entrada de texto de comentario, y utiliza una variable de estado `comment` para guardar su valor. Un día, te das cuenta de un problema: cuando navegas de un perfil a otro, el estado `comment` no se reinicia. Como resultado, es fácil publicar accidentalmente un comentario en el perfil de un usuario incorrecto. Para solucionar el problema, quieres limpiar la variable de estado `comment` cada vez que el `userId` cambie: From 8a1cb6064e52b1295f169ac3c1136230869bc55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:51:03 -0300 Subject: [PATCH 029/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 1125b437c..5cf1b8dab 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -224,7 +224,7 @@ function List({ items }) { const [isReverse, setIsReverse] = useState(false); const [selection, setSelection] = useState(null); - // Una mejor práctica: Actualizar el estado al renderizar + // Mejor: Ajusta el estado durante el renderizado. const [prevItems, setPrevItems] = useState(items); if (items !== prevItems) { setPrevItems(items); From 57f864f73e4141cf76935219e9b08df542a39d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:51:16 -0300 Subject: [PATCH 030/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 5cf1b8dab..65bad37b9 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -215,7 +215,7 @@ function List({ items }) { } ``` -Esto tampoco es ideal. Debido a que cada vez que los `items` cambien, `List` y sus componentes hijos renderizarán con un valor `selection` obsoleto al comienzo. Luego React actualizará el DOM y ejecutará los Efectos. Finalmente, la llamada a `setSelection(null)` provocará otro renderizado de `List` y sus componentes hijos, nuevamente reiniciando por completo este proceso. +Esto, también, no es ideal. Cada vez que cambian los `items`, el componente `List` y sus componentes hijos se renderizarán inicialmente con un valor obsoleto de `selection`. Luego, React actualizará el DOM y ejecutará los Efectos. Finalmente, la llamada a `setSelection(null)` provocará otra nueva renderización del componente `List` y sus componentes hijos, reiniciando todo este proceso nuevamente. Comienza por eliminar el Efecto. En su lugar, ajusta el estado directamente durante el renderizado: From 97302c111d7ccb86510e40d68f63fa5fd29656c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:51:30 -0300 Subject: [PATCH 031/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 65bad37b9..f9361b86d 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -234,7 +234,7 @@ function List({ items }) { } ``` -[Almacenar información de renderizados anteriores](/reference/react/useState#storing-information-from-previous-renders) de esta manera puede ser difícil de entender, pero es mejor que actualizar el mismo estado en un Efecto. En el ejemplo anterior, `setSelection` se llama directamente durante un renderizado. React volverá a renderizar `List` *inmediatamente* después de su declaración `return`. React aún no ha renderizado los hijos de `List` ni ha actualizado el DOM, por lo que esto permite que los hijos de `List` omitan el renderizar el valor obsoleto de `selection`. +[Almacenar información de renderizados previos](/reference/react/useState#storing-information-from-previous-renders) como se muestra en este ejemplo puede ser difícil de entender, pero es mejor que actualizar el mismo estado en un Efecto. En el ejemplo anterior, `setSelection` se llama directamente durante un renderizado. React volverá a renderizar el componente `List` *inmediatamente* después de salir del bloque de `return`. React aún no ha renderizado los hijos de `List` ni ha actualizado el DOM, lo que permite a los hijos de `List` omitir el renderizado del valor obsoleto de `selection`. Cuando actualizas un componente durante el renderizado, React descarta el JSX devuelto e intenta inmediatamente el renderizado nuevamente. Para evitar reintentos en cascada muy lentos, React solo te permite actualizar el estado del *mismo* componente durante un renderizado. Si actualizas el estado de otro componente durante un renderizado, verás un error. Una condición como `items !== prevItems` es necesaria para evitar bucles. Puedes ajustar el estado de esta manera, pero cualquier otro efecto secundario (como cambiar el DOM o establecer timeouts) debe permanecer en manejadores de eventos o Efectos para [mantener a los componentes puros.](/learn/keeping-components-pure) From d4a94091ce12b7095aca73b21d4a3ef1cf2bc5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:51:42 -0300 Subject: [PATCH 032/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index f9361b86d..f330fb67b 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -722,7 +722,7 @@ No importa de dónde vengan `page` y `query`. Mientras este componente sea visib Sin embargo, el código anterior tiene un error. Imagina que escribes "hola" rápidamente. Entonces la `query` cambiará de "h", a "ho", "hol", y "hola". Esto iniciará búsquedas separadas, pero no hay garantía sobre el orden en que llegarán las respuestas. Por ejemplo, la respuesta "hol" puede llegar *después* de la respuesta "hola". Como "hol" llamará a `setResults()` al final, estarás mostrando los resultados de búsqueda incorrectos. Esto se llama una ["condición de carrera"](https://es.wikipedia.org/wiki/Condición_de_carrera): dos solicitudes diferentes "compitieron" entre sí y llegaron en un orden diferente al que esperabas. -**Para corregir la condición de carrera, tendrás que [agregar una función de limpieza](/learn/synchronizing-with-effects#fetching-data) para ignorar las respuestas obsoletas:** +**Para solucionar la condición de carrera, necesitas [agregar una función de limpieza](/learn/synchronizing-with-effects#fetching-data) para ignorar respuestas obsoletas:** ```js {5,7,9,11-13} function SearchResults({ query }) { From e2a9e2b70f5edf8afdbfe30ca5f20bbfc33f405c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:51:56 -0300 Subject: [PATCH 033/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index f330fb67b..a1fd238c0 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -236,7 +236,7 @@ function List({ items }) { [Almacenar información de renderizados previos](/reference/react/useState#storing-information-from-previous-renders) como se muestra en este ejemplo puede ser difícil de entender, pero es mejor que actualizar el mismo estado en un Efecto. En el ejemplo anterior, `setSelection` se llama directamente durante un renderizado. React volverá a renderizar el componente `List` *inmediatamente* después de salir del bloque de `return`. React aún no ha renderizado los hijos de `List` ni ha actualizado el DOM, lo que permite a los hijos de `List` omitir el renderizado del valor obsoleto de `selection`. -Cuando actualizas un componente durante el renderizado, React descarta el JSX devuelto e intenta inmediatamente el renderizado nuevamente. Para evitar reintentos en cascada muy lentos, React solo te permite actualizar el estado del *mismo* componente durante un renderizado. Si actualizas el estado de otro componente durante un renderizado, verás un error. Una condición como `items !== prevItems` es necesaria para evitar bucles. Puedes ajustar el estado de esta manera, pero cualquier otro efecto secundario (como cambiar el DOM o establecer timeouts) debe permanecer en manejadores de eventos o Efectos para [mantener a los componentes puros.](/learn/keeping-components-pure) +Cuando actualizas un componente durante el renderizado, React descarta el JSX devuelto y vuelve a intentar el renderizado de inmediato. Para evitar reintentos en cascada muy lentos, React solo te permite actualizar el estado del *mismo* componente durante el renderizado. Si intentas actualizar el estado de otro componente durante el renderizado, verás un error. Una condición como `items !== prevItems` es necesaria para evitar bucles. Puedes ajustar el estado de esta manera, pero cualquier otro efecto secundario (como cambios en el DOM o establecer tiempos de espera) debe mantenerse en los controladores de eventos o en Efectos para [mantener los componentes puros.](/learn/keeping-components-pure) **Aunque este patrón es más eficiente que un Efecto, la mayoría de los componentes tampoco deberían necesitarlo.** No importa cómo lo hagas, ajustar el estado basado en las props u otro estado hace que tu flujo de datos sea más difícil de entender y depurar. Siempre verifica si puedes [resetear todo el estado con una key](#resetting-all-state-when-a-prop-changes) o [calcular todo durante el renderizado](#updating-state-based-on-props-or-state) en su lugar. Por ejemplo, en lugar de almacenar (y resetear) el *ítem* seleccionado, puedes almacenar el *ID del ítem seleccionado*: From 8524ea102cd792abbe13635345a1e9379fe0aaf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:52:09 -0300 Subject: [PATCH 034/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index a1fd238c0..1ba5a6b50 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -250,7 +250,7 @@ function List({ items }) { } ``` -Ahora no hay necesidad de "ajustar" el estado en lo absoluto. Si el elemento con el ID seleccionado está en la lista, permanecerá seleccionado. Si no lo está, la `selection` calculada durante el renderizado será `null` porque no se encontró ningún elemento coincidente. Este comportamiento es diferente, pero se podría decir que es mejor porque la mayoría de los cambios en `items` preservan la selección. +Ahora no hay necesidad de "ajustar" el estado en lo absoluto. Si el _item_ con el ID seleccionado está en la lista, permanecerá seleccionado. Si no lo está, la `selection` calculada durante el renderizado será `null` porque no se encontró ningún _item_ coincidente. Este comportamiento es diferente, pero se podría decir que es mejor porque la mayoría de los cambios en `items` preservan la selección. ### Compartir la lógica entre manejadores de eventos {/*sharing-logic-between-event-handlers*/} From 661f3424e58dd9a9a47b3edbaedcf035b464eaef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:52:48 -0300 Subject: [PATCH 035/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 1ba5a6b50..72cf37a6b 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -39,7 +39,7 @@ function Form() { const [firstName, setFirstName] = useState('Taylor'); const [lastName, setLastName] = useState('Swift'); - // 🔴 Desaconsejado: estado redundante y Efecto innecesario + // 🔴 Evitar: estado redundante y Efecto innecesario const [fullName, setFullName] = useState(''); useEffect(() => { setFullName(firstName + ' ' + lastName); From bccfa180de3ede377c71a2a87575ab9b7fea9961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:53:23 -0300 Subject: [PATCH 036/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 72cf37a6b..f1e67cf6e 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -48,7 +48,7 @@ function Form() { } ``` -Esto es más complicado de lo necesario. También es ineficiente: desencadena un ciclo completo de renderizado con un valor antiguo para `fullName`, y luego inmediatamente vuelve a renderizar con el valor actualizado. Es mejor que elimines tanto la variable de estado como el efecto: +Esto es más complicado de lo necesario. También es ineficiente: realiza un pase de renderización completo con un valor obsoleto para `fullName`, y luego se vuelve a renderizar inmediatamente con el valor actualizado. Elimina la variable de estado y el Efecto: ```js {4-5} function Form() { From dfa728a992b61b1358d3bd3140aee7b5eeb60b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:53:45 -0300 Subject: [PATCH 037/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index f1e67cf6e..1bdfffcfd 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -54,7 +54,7 @@ Esto es más complicado de lo necesario. También es ineficiente: realiza un pas function Form() { const [firstName, setFirstName] = useState('Taylor'); const [lastName, setLastName] = useState('Swift'); - // ✅ Buena práctica: calcularlo durante el renderizado + // ✅ Correcto: calculado durante el renderizado. const fullName = firstName + ' ' + lastName; // ... } From 91b5d227da3784b420c65100fd5a221df75b524f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:54:04 -0300 Subject: [PATCH 038/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 1bdfffcfd..74cb1b598 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -60,7 +60,7 @@ function Form() { } ``` -**Cuando algo puede ser calculado a partir de las props o el estado existente, [no lo pongas en un nuevo estado.](/learn/choosing-the-state-structure#avoid-redundant-state) Es mejor calcularlo durante el renderizado.** Esta manera hace que tu código sea más rápido (evitas las actualizaciones extra "en cascada"), más simple (te ahorras algo de código), y menos propenso a errores (evitas errores causados por diferentes variables de estado que no están sincronizadas entre sí). Si este enfoque es nuevo para ti, [pensar en React](/learn/thinking-in-react#step-3-find-the-minimal-but-complete-representation-of-ui-state) tiene algunas orientaciones sobre lo que debería ir en el estado. +**Cuando algo puede calcularse a partir de las _props_ o el estado existente, [no lo pongas en el estado](/learn/choosing-the-state-structure#avoid-redundant-state). En su lugar, calcúlalo durante el renderizado.** Esto hace que tu código sea más rápido (evitas las actualizaciones adicionales "en cascada"), más simple (eliminas código innecesario) y menos propenso a errores (evitas errores causados por diferentes variables de estado desincronizadas entre sí). Si este enfoque te resulta nuevo, [Pensar en React](/learn/thinking-in-react#step-3-find-the-minimal-but-complete-representation-of-ui-state) explica qué debe ir en el estado. ### Almacenar en caché los cálculos costosos {/*caching-expensive-calculations*/} From 223197815bd2fc57c49b15a4ba6fb5ad8789cb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:54:23 -0300 Subject: [PATCH 039/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 74cb1b598..ac52daee3 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -62,7 +62,7 @@ function Form() { **Cuando algo puede calcularse a partir de las _props_ o el estado existente, [no lo pongas en el estado](/learn/choosing-the-state-structure#avoid-redundant-state). En su lugar, calcúlalo durante el renderizado.** Esto hace que tu código sea más rápido (evitas las actualizaciones adicionales "en cascada"), más simple (eliminas código innecesario) y menos propenso a errores (evitas errores causados por diferentes variables de estado desincronizadas entre sí). Si este enfoque te resulta nuevo, [Pensar en React](/learn/thinking-in-react#step-3-find-the-minimal-but-complete-representation-of-ui-state) explica qué debe ir en el estado. -### Almacenar en caché los cálculos costosos {/*caching-expensive-calculations*/} +### Almacenamiento en caché de cálculos costosos{/*caching-expensive-calculations*/} Este componente calcula `visibleTodos` tomando los `todos` que recibe a través de _props_ y filtrándolos según la _prop_ `filter`. Podrías sentirte tentado/a de almacenar el resultado en el estado y actualizarlo desde un Efecto: From 0a28c56995a3e7e885b1901f96f3bdf770487ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:54:43 -0300 Subject: [PATCH 040/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index ac52daee3..6d448ad8b 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -101,7 +101,7 @@ import { useMemo, useState } from 'react'; function TodoList({ todos, filter }) { const [newTodo, setNewTodo] = useState(''); const visibleTodos = useMemo(() => { - // ✅ No se volverá a ejecutar a menos que todos o filter cambien + // ✅ No se vuelve a ejecutar a menos que cambien todos o filter. return getFilteredTodos(todos, filter); }, [todos, filter]); // ... From 22eccabcb61a7b4b54cd0ddf4934896cbbde11eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:55:03 -0300 Subject: [PATCH 041/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 6d448ad8b..5e713ba0c 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -123,7 +123,7 @@ function TodoList({ todos, filter }) { **Esto le indica a React que no deseas que la función interna se vuelva a ejecutar a menos que `todos` o `filter` hayan cambiado.** React recordará el valor de retorno de `getFilteredTodos()` durante el renderizado inicial. Durante los siguientes renderizados, verificará si `todos` o `filter` son diferentes. Si son iguales que la última vez, `useMemo` devolverá el último resultado almacenado. Pero si son diferentes, React llamará nuevamente a la función interna (y almacenará su resultado). -La función que envuelves en el Hook de React [`useMemo`](/reference/react/useMemo) se ejecuta durante el renderizado, por lo que solo funcionará para [cálculos puros.](/learn/keeping-components-pure) +La función que envuelves en [`useMemo`](/reference/react/useMemo) se ejecuta durante el renderizado, por lo que esto solo funciona para [cálculos puros.](/learn/keeping-components-pure) From ed38e3fb5a1a8c546a07336a260af90f2c5a9e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:56:02 -0300 Subject: [PATCH 042/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 5e713ba0c..2b743ec28 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -127,7 +127,7 @@ La función que envuelves en [`useMemo`](/reference/react/useMemo) se ejecuta du -#### ¿Cómo saber si un cálculo es costoso? {/*how-to-tell-if-a-calculation-is-expensive*/} +#### ¿Cómo determinar si un cálculo es costoso? {/*how-to-tell-if-a-calculation-is-expensive*/} En general, a menos que estés creando o iterando sobre miles de objetos, probablemente no sea costoso. Si quieres tener más confianza, puedes imprimirlo en la consola y medir el tiempo que pasa en ese fragmento de código: From ba3775bd753fe68f3aea60a4c9d407fbc7fe0837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:56:25 -0300 Subject: [PATCH 043/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 2b743ec28..88ddc406f 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -129,7 +129,7 @@ La función que envuelves en [`useMemo`](/reference/react/useMemo) se ejecuta du #### ¿Cómo determinar si un cálculo es costoso? {/*how-to-tell-if-a-calculation-is-expensive*/} -En general, a menos que estés creando o iterando sobre miles de objetos, probablemente no sea costoso. Si quieres tener más confianza, puedes imprimirlo en la consola y medir el tiempo que pasa en ese fragmento de código: +En general, a menos que estés creando o iterando sobre miles de objetos, probablemente no es costoso. Si deseas tener más confianza, puedes agregar un registro en la consola para medir el tiempo que se tarda en ejecutar una pieza de código: ```js {1,3} console.time('filter array'); From dd61e8e0fd92fcdfcd54c0b8d5d43837f191b688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:57:09 -0300 Subject: [PATCH 044/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 88ddc406f..0055d0e62 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -446,7 +446,7 @@ function Game() { // ... ``` -Esto es mucho más eficiente. Además, si implementas una forma de ver el historial del juego, ahora podrás establecer cada variable de estado a un movimiento del pasado sin activar la cadena de Efectos que ajusta todos los demás valores. Si necesitas reutilizar la lógica entre varios manejadores de eventos, puedes [extraer una función](#sharing-logic-between-event-handlers) y llamarla desde esos manejadores. +Esto es mucho más eficiente. Además, si implementas una forma de ver el historial del juego, ahora podrás establecer cada variable de estado en un movimiento del pasado sin activar la cadena de Efectos que ajusta cada otro valor. Si necesitas reutilizar la lógica entre varios controladores de eventos, puedes [extraer una función](#sharing-logic-between-event-handlers) y llamarla desde esos controladores. Recuerda que dentro de los manejadores de eventos, [el estado se comporta como una instantánea.](/learn/state-as-a-snapshot) Por ejemplo, incluso después de llamar a `setRound(round + 1)`, la variable `round` reflejará el valor en el momento en que el usuario hizo clic en el botón. Si necesitas usar el siguiente valor para cálculos, defínelo manualmente como `const nextRound = round + 1`. From d02bd47bcab7c8030b8b83c73f0e12ee7283e74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:57:23 -0300 Subject: [PATCH 045/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 0055d0e62..32c72ed15 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -448,7 +448,7 @@ function Game() { Esto es mucho más eficiente. Además, si implementas una forma de ver el historial del juego, ahora podrás establecer cada variable de estado en un movimiento del pasado sin activar la cadena de Efectos que ajusta cada otro valor. Si necesitas reutilizar la lógica entre varios controladores de eventos, puedes [extraer una función](#sharing-logic-between-event-handlers) y llamarla desde esos controladores. -Recuerda que dentro de los manejadores de eventos, [el estado se comporta como una instantánea.](/learn/state-as-a-snapshot) Por ejemplo, incluso después de llamar a `setRound(round + 1)`, la variable `round` reflejará el valor en el momento en que el usuario hizo clic en el botón. Si necesitas usar el siguiente valor para cálculos, defínelo manualmente como `const nextRound = round + 1`. +Recuerda que dentro de los controladores de eventos, [el estado se comporta como una instantánea.](/learn/state-as-a-snapshot) Por ejemplo, incluso después de llamar a `setRound(round + 1)`, la variable `round` reflejará el valor en el momento en que el usuario hizo clic en el botón. Si necesitas usar el siguiente valor para cálculos, defínelo manualmente como `const nextRound = round + 1`. En algunos casos, *no puedes* calcular el siguiente estado directamente en el manejador de eventos. Por ejemplo, imagina un formulario con múltiples desplegables donde las opciones del siguiente desplegable dependen del valor seleccionado del desplegable anterior. Entonces, una cadena de Efectos es apropiada porque estás sincronizando con la red. From ec01cf70c31e8e08bf27d75929397ece9d32fb7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:57:38 -0300 Subject: [PATCH 046/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 32c72ed15..ae55ab5cf 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -450,7 +450,7 @@ Esto es mucho más eficiente. Además, si implementas una forma de ver el histor Recuerda que dentro de los controladores de eventos, [el estado se comporta como una instantánea.](/learn/state-as-a-snapshot) Por ejemplo, incluso después de llamar a `setRound(round + 1)`, la variable `round` reflejará el valor en el momento en que el usuario hizo clic en el botón. Si necesitas usar el siguiente valor para cálculos, defínelo manualmente como `const nextRound = round + 1`. -En algunos casos, *no puedes* calcular el siguiente estado directamente en el manejador de eventos. Por ejemplo, imagina un formulario con múltiples desplegables donde las opciones del siguiente desplegable dependen del valor seleccionado del desplegable anterior. Entonces, una cadena de Efectos es apropiada porque estás sincronizando con la red. +En algunos casos, *no puedes* calcular el siguiente estado directamente en el controlador de eventos. Por ejemplo, imagina un formulario con múltiples menús desplegables donde las opciones del siguiente menú desplegable dependen del valor seleccionado en el menú desplegable anterior. En este caso, una cadena de Efectos es apropiada porque estás sincronizando con la red. ### Inicializar la aplicación {/*initializing-the-application*/} From a25ec9cf6bc935aab417606369936503870afb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:57:51 -0300 Subject: [PATCH 047/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index ae55ab5cf..5489b75bb 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -454,7 +454,7 @@ En algunos casos, *no puedes* calcular el siguiente estado directamente en el co ### Inicializar la aplicación {/*initializing-the-application*/} -Algunas lógicas sólo deben ejecutarse una vez cuando se carga la aplicación. +Alguna lógica solo debería ejecutarse una vez cuando se carga la aplicación. Podrías estar tentado a colocarla en un Efecto en el componente de nivel superior: From 0eb7cd57d1aabb818a1e234d2b5a334952e92621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:58:04 -0300 Subject: [PATCH 048/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 5489b75bb..aa8215745 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -456,7 +456,7 @@ En algunos casos, *no puedes* calcular el siguiente estado directamente en el co Alguna lógica solo debería ejecutarse una vez cuando se carga la aplicación. -Podrías estar tentado a colocarla en un Efecto en el componente de nivel superior: +Podrías sentirte tentado a colocarla en un Efecto en el componente de nivel superior: ```js {2-6} function App() { From 8d560acaf7dcdaf354618ad8d8cbb9bd451e1947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:58:29 -0300 Subject: [PATCH 049/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index aa8215745..469ebacf4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -163,7 +163,7 @@ Este componente `ProfilePage` recibe una prop `userId`. La página contiene una export default function ProfilePage({ userId }) { const [comment, setComment] = useState(''); - // 🔴 Desaconsejado: Reiniciar el estado según cambio de prop en un Efecto + // 🔴 Evitar: Restablecer el estado en un cambio de prop dentro de un Efecto. useEffect(() => { setComment(''); }, [userId]); From 1437683dcb8fe4ae8e37d94b6f2cd52b91882d10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:59:01 -0300 Subject: [PATCH 050/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 469ebacf4..28f8f0b4e 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -207,7 +207,7 @@ function List({ items }) { const [isReverse, setIsReverse] = useState(false); const [selection, setSelection] = useState(null); - // 🔴 Desaconsejado: Ajustar el estado según un cambio de prop en un Efecto + // 🔴 Evitar: Ajustar el estado en un cambio de prop dentro de un Efecto. useEffect(() => { setSelection(null); }, [items]); From 44122b3ba91726a0f575a78698ee61bc97c742ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:59:17 -0300 Subject: [PATCH 051/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 28f8f0b4e..49ae82019 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -460,7 +460,7 @@ Podrías sentirte tentado a colocarla en un Efecto en el componente de nivel sup ```js {2-6} function App() { - // 🔴 Evitar: Efectos con lógica que sólo debería ejecutarse una vez + // 🔴 Evitar: Efectos con lógica que solo deben ejecutarse una vez. useEffect(() => { loadDataFromLocalStorage(); checkAuthToken(); From 08410b292ee828e3393cdaa33e3da8849c48a632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 13:59:57 -0300 Subject: [PATCH 052/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 49ae82019..d19b26d4b 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -469,7 +469,7 @@ function App() { } ``` -Sin embargo, rápidamente descubrirás que [se ejecuta dos veces en desarrollo.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) Esto puede causar problemas: por ejemplo, quizás invalida el token de autenticación porque la función no fue diseñada para ser llamada dos veces. En general, tus componentes deberían ser resistentes a ser desmontados. Esto incluye tu componente `App` de nivel superior. +Sin embargo, rápidamente descubrirás que esto [se ejecuta dos veces en desarrollo](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). Esto puede causar problemas, por ejemplo, tal vez invalide el _token_ de autenticación porque la función no fue diseñada para ser llamada dos veces. En general, tus componentes deberían ser resistentes a ser montados de nuevo. Esto incluye tu componente de nivel superior `App`. Aunque puede que nunca se desmonte en la práctica en producción, seguir las mismas restricciones en todos los componentes facilita mover y reutilizar el código. Si alguna lógica debe ejecutarse *una vez por carga de la aplicación* en lugar de *una vez por montaje del componente*, añade una variable de nivel superior para rastrear si ya se ha ejecutado: From 38717e5ea539f4d4a073d1107102b86104d3f81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:00:06 -0300 Subject: [PATCH 053/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index d19b26d4b..636e09d34 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -471,7 +471,7 @@ function App() { Sin embargo, rápidamente descubrirás que esto [se ejecuta dos veces en desarrollo](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development). Esto puede causar problemas, por ejemplo, tal vez invalide el _token_ de autenticación porque la función no fue diseñada para ser llamada dos veces. En general, tus componentes deberían ser resistentes a ser montados de nuevo. Esto incluye tu componente de nivel superior `App`. -Aunque puede que nunca se desmonte en la práctica en producción, seguir las mismas restricciones en todos los componentes facilita mover y reutilizar el código. Si alguna lógica debe ejecutarse *una vez por carga de la aplicación* en lugar de *una vez por montaje del componente*, añade una variable de nivel superior para rastrear si ya se ha ejecutado: +Aunque en la práctica en producción es posible que nunca se vuelva a montar, seguir las mismas restricciones en todos los componentes facilita mover y reutilizar el código. Si alguna lógica debe ejecutarse *una vez por carga de la aplicación* en lugar de *una vez por montaje del componente*, agrega una variable de nivel superior para llevar un registro de si ya se ha ejecutado: ```js {1,5-6,10} let didInit = false; From 8b5a8332a3ff58ec982e8eefe5e2ff1d72e26703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:00:14 -0300 Subject: [PATCH 054/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 636e09d34..79c6b3a1e 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -480,7 +480,7 @@ function App() { useEffect(() => { if (!didInit) { didInit = true; - // ✅ Solo se ejecuta una vez por carga de la aplicación + // ✅ Se ejecuta solo una vez por carga de la aplicación. loadDataFromLocalStorage(); checkAuthToken(); } From 3b6286ba37b53b4323e1bb0b045ffef6cc61f078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:00:22 -0300 Subject: [PATCH 055/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 79c6b3a1e..c4aa3d1df 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -503,7 +503,7 @@ function App() { } ``` -El código en el nivel superior se ejecuta una vez cuando se importa tu componente, incluso si no termina siendo renderizado. Para evitar ralentizaciones o comportamientos inesperados al importar componentes arbitrarios, no abuses de este patrón. Mantén la lógica de inicialización de la aplicación en los módulos de componentes raíz como `App.js` o en el punto de entrada de tu aplicación. +El código en el nivel superior se ejecuta una vez cuando se importa tu componente, incluso si no se llega a renderizar. Para evitar ralentización o comportamientos inesperados al importar componentes arbitrarios, no abuses de este patrón. Mantén la lógica de inicialización a nivel de la aplicación en módulos de componentes _root_, como `App.js`, o en el punto de entrada de tu aplicación. ### Notificar a los componentes padre sobre cambios de estado {/*notifying-parent-components-about-state-changes*/} From 27bb6bc9bb4e44935fbb8ab8c2a44481d639c3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:00:29 -0300 Subject: [PATCH 056/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index c4aa3d1df..5b6264542 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -794,7 +794,7 @@ En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes - Si puedes calcular algo durante el renderizado, no necesitas un Efecto. - Para almacenar en caché cálculos costosos, utiliza `useMemo` en lugar de `useEffect`. -- Para restablecer el estado de un árbol de componentes completo, pásale una `key` diferente. +- Para restablecer el estado de todo el árbol de componentes, pasa una `key` diferente a este. - Para restablecer una porción de estado en respuesta a un cambio de prop, configúralo durante el renderizado. - El código que se ejecuta porque un componente se *mostró* al usuario debería estar en Efectos, el resto debería estar en eventos. - Si necesitas actualizar el estado de varios componentes, es mejor hacerlo durante un solo evento. From c58bf624e726a2857554b1dfeb4e45261010cc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:00:38 -0300 Subject: [PATCH 057/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 5b6264542..429082da4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -796,7 +796,7 @@ En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes - Para almacenar en caché cálculos costosos, utiliza `useMemo` en lugar de `useEffect`. - Para restablecer el estado de todo el árbol de componentes, pasa una `key` diferente a este. - Para restablecer una porción de estado en respuesta a un cambio de prop, configúralo durante el renderizado. -- El código que se ejecuta porque un componente se *mostró* al usuario debería estar en Efectos, el resto debería estar en eventos. +- El código que se ejecuta porque un componente fue *mostrado* debería estar en Efectos, el resto debería estar en eventos. - Si necesitas actualizar el estado de varios componentes, es mejor hacerlo durante un solo evento. - Siempre que intentes sincronizar variables de estado en diferentes componentes, considera elevar el estado. - Puedes obtener datos con Efectos, pero necesitas implementar limpieza para evitar condiciones de carrera. From be94125da72fd6c515f742e278748c56f8e81704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:00:47 -0300 Subject: [PATCH 058/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 429082da4..d71385f60 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -795,7 +795,7 @@ En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes - Si puedes calcular algo durante el renderizado, no necesitas un Efecto. - Para almacenar en caché cálculos costosos, utiliza `useMemo` en lugar de `useEffect`. - Para restablecer el estado de todo el árbol de componentes, pasa una `key` diferente a este. -- Para restablecer una porción de estado en respuesta a un cambio de prop, configúralo durante el renderizado. +- Para restablecer una porción del estado en respuesta a un cambio de _prop_, establécelo durante el renderizado. - El código que se ejecuta porque un componente fue *mostrado* debería estar en Efectos, el resto debería estar en eventos. - Si necesitas actualizar el estado de varios componentes, es mejor hacerlo durante un solo evento. - Siempre que intentes sincronizar variables de estado en diferentes componentes, considera elevar el estado. From 513e08332b209925840b066161294bbba37f1de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:00:54 -0300 Subject: [PATCH 059/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index d71385f60..d83ea52da 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -798,7 +798,7 @@ En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes - Para restablecer una porción del estado en respuesta a un cambio de _prop_, establécelo durante el renderizado. - El código que se ejecuta porque un componente fue *mostrado* debería estar en Efectos, el resto debería estar en eventos. - Si necesitas actualizar el estado de varios componentes, es mejor hacerlo durante un solo evento. -- Siempre que intentes sincronizar variables de estado en diferentes componentes, considera elevar el estado. +- Siempre que intentes sincronizar variables de estado en diferentes componentes, considera levantar el estado. - Puedes obtener datos con Efectos, pero necesitas implementar limpieza para evitar condiciones de carrera. From 06189483ac438f8f8474e9aa20054413e52d52b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:01:24 -0300 Subject: [PATCH 060/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index d83ea52da..f153ddc2e 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -258,7 +258,7 @@ Supongamos que tienes una página de producto con dos botones (Comprar y Pagar) ```js {2-7} function ProductPage({ product, addToCart }) { - // 🔴 Evita: Lógica específica para evento dentro de un Efecto + // 🔴 Evitar: Lógica específica del evento dentro de un Efecto. useEffect(() => { if (product.isInCart) { showNotification(`Added ${product.name} to the shopping cart!`); From aed70d463f991c692f8cccbcb379affe821caa42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:02:02 -0300 Subject: [PATCH 061/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index f153ddc2e..41ad41b11 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -147,7 +147,7 @@ const visibleTodos = useMemo(() => { console.timeEnd('filter array'); ``` -`useMemo` no hará que el *primer* renderizado sea más rápido. Solo te ayuda a evitar trabajo innecesario en las actualizaciones. +`useMemo` no hará que el *primer* renderizado sea más rápido. Solo te ayuda a evitar trabajo innecesario en las actualizaciones posteriores. Ten en cuenta que tu máquina probablemente sea más rápida que la de tus usuarios, por lo que es una buena idea probar el rendimiento con una ralentización artificial. Por ejemplo, Chrome ofrece una opción de [limitación de CPU](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) para esto. From 597722f520a613dd3724f553d55dd75202218250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:02:17 -0300 Subject: [PATCH 062/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 41ad41b11..b3c02b201 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -149,7 +149,7 @@ console.timeEnd('filter array'); `useMemo` no hará que el *primer* renderizado sea más rápido. Solo te ayuda a evitar trabajo innecesario en las actualizaciones posteriores. -Ten en cuenta que tu máquina probablemente sea más rápida que la de tus usuarios, por lo que es una buena idea probar el rendimiento con una ralentización artificial. Por ejemplo, Chrome ofrece una opción de [limitación de CPU](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) para esto. +Ten en cuenta que tu máquina probablemente es más rápida que la de tus usuarios, por lo que es una buena idea probar el rendimiento con una ralentización artificial. Por ejemplo, Chrome ofrece una opción de [Limitación de CPU](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) para esto. También ten en cuenta que medir el rendimiento en desarrollo no te dará los resultados más precisos. (Por ejemplo, cuando [Modo Estricto](/reference/react/StrictMode) está activado, verás que cada componente se renderiza dos veces en lugar de una). Para obtener los tiempos más precisos, construye tu aplicación para producción y pruébala en un dispositivo similar al que usan tus usuarios. From 238f98728fe2eb2a34688809c5a169ef72dccbd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:03:12 -0300 Subject: [PATCH 063/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index b3c02b201..566dbadd4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -173,7 +173,7 @@ export default function ProfilePage({ userId }) { Esto es ineficiente porque `ProfilePage` y sus hijos primero se renderizarán con el valor obsoleto, y luego se renderizarán de nuevo. También es complicado porque necesitarías hacer esto en *cada* componente que tenga algún estado dentro de `ProfilePage`. Por ejemplo, si la interfaz de usuario del comentario está anidada, también querrías limpiar el estado del comentario anidado. -En lugar de ello, puedes decirle a React que cada perfil de usuario es conceptualmente un perfil _diferente_ dándole una _key_ explícita. Divide tu componente en dos y pasa un atributo `key` del componente exterior al interior: +En su lugar, puedes indicarle a React que el perfil de cada usuario es conceptualmente un perfil _diferente_ al proporcionarle una _key_ explícita. Divide tu componente en dos y pasa un atributo _`key`_ desde el componente externo al interno: ```js {5,11-12} export default function ProfilePage({ userId }) { From 95c02ec8283d3f17b76210d6403c4325ced662ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:03:43 -0300 Subject: [PATCH 064/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 566dbadd4..dd07478fe 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -157,7 +157,7 @@ También ten en cuenta que medir el rendimiento en desarrollo no te dará los re ### Restablecer todo el estado cuando una _prop_ cambia {/*resetting-all-state-when-a-prop-changes*/} -Este componente `ProfilePage` recibe una prop `userId`. La página contiene una entrada de texto de comentario, y utiliza una variable de estado `comment` para guardar su valor. Un día, te das cuenta de un problema: cuando navegas de un perfil a otro, el estado `comment` no se reinicia. Como resultado, es fácil publicar accidentalmente un comentario en el perfil de un usuario incorrecto. Para solucionar el problema, quieres limpiar la variable de estado `comment` cada vez que el `userId` cambie: +Este componente `ProfilePage` recibe una _prop_ `userId`. La página contiene una _input_ (entrada) de comentario, y tú usas una variable de estado `comment` para mantener este valor. Un día, tú te das cuenta de un problema: cuando navegas de un perfil a otro, el estado `comment` no se reinicia. Como resultado, es fácil publicar accidentalmente un comentario en el perfil de un usuario equivocado. Para arreglar el problema, tú quieres borrar la variable de estado `comment` cada vez que el `userId` cambie: ```js {4-7} export default function ProfilePage({ userId }) { From efd4f4ee1226c223f4086567df851b9ec359de40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:04:37 -0300 Subject: [PATCH 065/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index dd07478fe..22f82798d 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -171,7 +171,7 @@ export default function ProfilePage({ userId }) { } ``` -Esto es ineficiente porque `ProfilePage` y sus hijos primero se renderizarán con el valor obsoleto, y luego se renderizarán de nuevo. También es complicado porque necesitarías hacer esto en *cada* componente que tenga algún estado dentro de `ProfilePage`. Por ejemplo, si la interfaz de usuario del comentario está anidada, también querrías limpiar el estado del comentario anidado. +Esto es ineficiente porque `ProfilePage` y sus hijos se renderizarán primero con el valor obsoleto, y luego se volverán a renderizar. También es complicado porque tendrías que hacer esto en *cada* componente que tenga algún estado dentro de `ProfilePage`. Por ejemplo, si la UI de comentarios está anidada, también querrías restablecer el estado de los comentarios anidados. En su lugar, puedes indicarle a React que el perfil de cada usuario es conceptualmente un perfil _diferente_ al proporcionarle una _key_ explícita. Divide tu componente en dos y pasa un atributo _`key`_ desde el componente externo al interno: From bcd12f9a82af10eeb9d75b01ea4a170c9912d872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:05:02 -0300 Subject: [PATCH 066/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 22f82798d..cc9c0451b 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -186,7 +186,7 @@ export default function ProfilePage({ userId }) { } function Profile({ userId }) { - // ✅ Esto y cualquier otro estado a continuación se reiniciará automáticamente al cambiar la key + // ✅ Esto y cualquier otro estado a continuación se restablecerán automáticamente cuando cambie la key. const [comment, setComment] = useState(''); // ... } From 1aff17d66e1cd0d5bed628baf90d011ef19abc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:05:23 -0300 Subject: [PATCH 067/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index cc9c0451b..ac1a148f4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -192,7 +192,7 @@ function Profile({ userId }) { } ``` -Usualmente, React conserva el estado cuando el mismo componente se renderiza en el mismo lugar. **Al pasar `userId` como una `key` al componente `Profile`, le estás pidiendo a React que trate a dos componentes `Profile` con diferentes `userId` como dos componentes diferentes que no deberían compartir ningún estado.** Cuando la key (que has establecido como `userId`) cambie, React recreará el DOM y [reiniciará el estado](/learn/preserving-and-resetting-state#option-2-resetting-state-with-a-key) del componente `Profile` y todos sus hijos. Ahora el campo `comment` se borrará automáticamente cuando se navegue entre perfiles. +Normalmente, React preserva el estado cuando el mismo componente se renderiza en el mismo lugar. **Al pasar `userId` como una _`key`_ al componente `Profile`, le estás indicando a React que trate dos componentes `Profile` con diferentes `userId` como dos componentes diferentes que no deben compartir ningún estado.** Cada vez que cambie la _key_ (que has establecido como `userId`), React recreará el DOM y [restablecerá el estado](/learn/preserving-and-resetting-state#option-2-resetting-state-with-a-key) del componente `Profile` y de todos sus hijos. Ahora, el campo `comment` se borrará automáticamente al navegar entre perfiles. Ten en cuenta que en este ejemplo, solo el componente externo `ProfilePage` es exportado y visible para otros archivos en el proyecto. Los componentes que renderizan `ProfilePage` no necesitan pasar la key a este: pasan `userId` como una prop regular. El hecho de que `ProfilePage` lo pase como una `key` al componente interno `Profile` es un detalle de implementación. From a610c3560b51b0e879282cbc094069dd53d622e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:05:36 -0300 Subject: [PATCH 068/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index ac1a148f4..0924b4b37 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -194,7 +194,7 @@ function Profile({ userId }) { Normalmente, React preserva el estado cuando el mismo componente se renderiza en el mismo lugar. **Al pasar `userId` como una _`key`_ al componente `Profile`, le estás indicando a React que trate dos componentes `Profile` con diferentes `userId` como dos componentes diferentes que no deben compartir ningún estado.** Cada vez que cambie la _key_ (que has establecido como `userId`), React recreará el DOM y [restablecerá el estado](/learn/preserving-and-resetting-state#option-2-resetting-state-with-a-key) del componente `Profile` y de todos sus hijos. Ahora, el campo `comment` se borrará automáticamente al navegar entre perfiles. -Ten en cuenta que en este ejemplo, solo el componente externo `ProfilePage` es exportado y visible para otros archivos en el proyecto. Los componentes que renderizan `ProfilePage` no necesitan pasar la key a este: pasan `userId` como una prop regular. El hecho de que `ProfilePage` lo pase como una `key` al componente interno `Profile` es un detalle de implementación. +Ten en cuenta que en este ejemplo, solo el componente `ProfilePage` externo es exportado y visible para otros archivos en el proyecto. Los componentes que renderizan `ProfilePage` no necesitan pasar la _key_; simplemente pasan `userId` como una _prop_ regular. El hecho de que `ProfilePage` lo pase como una _`key`_ al componente interno `Profile` es un detalle de implementación. ### Actualizar parte del estado cuando cambie una prop {/*adjusting-some-state-when-a-prop-changes*/} From b09498e3d5080bccbac501a2e74c17aadcfee64e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:07:54 -0300 Subject: [PATCH 069/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 0924b4b37..5fef833b8 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -196,7 +196,7 @@ Normalmente, React preserva el estado cuando el mismo componente se renderiza en Ten en cuenta que en este ejemplo, solo el componente `ProfilePage` externo es exportado y visible para otros archivos en el proyecto. Los componentes que renderizan `ProfilePage` no necesitan pasar la _key_; simplemente pasan `userId` como una _prop_ regular. El hecho de que `ProfilePage` lo pase como una _`key`_ al componente interno `Profile` es un detalle de implementación. -### Actualizar parte del estado cuando cambie una prop {/*adjusting-some-state-when-a-prop-changes*/} +### Ajustar algún estado cuando cambia una _prop_ {/*adjusting-some-state-when-a-prop-changes*/} A veces, querrás resetear o ajustar una parte del estado según un cambio de prop, pero no todo. From ac398eb2f02dbb6702694f89e6a28dbf9fbc5ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:08:10 -0300 Subject: [PATCH 070/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 5fef833b8..10415962f 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -198,7 +198,7 @@ Ten en cuenta que en este ejemplo, solo el componente `ProfilePage` externo es e ### Ajustar algún estado cuando cambia una _prop_ {/*adjusting-some-state-when-a-prop-changes*/} -A veces, querrás resetear o ajustar una parte del estado según un cambio de prop, pero no todo. +A veces, es posible que desees restablecer o ajustar una parte del estado cuando cambie una _prop_, pero no todo el estado. Este componente `List` recibe una lista de `items` como una prop y mantiene el elemento seleccionado en la variable de estado `selection`. Tu objetivo es resetear `selection` a `null` siempre que la prop `items` reciba un array diferente: From f53d76ec93bd8f9fe22c07653ca606797fa22b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:08:24 -0300 Subject: [PATCH 071/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 10415962f..34fcc878e 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -200,7 +200,7 @@ Ten en cuenta que en este ejemplo, solo el componente `ProfilePage` externo es e A veces, es posible que desees restablecer o ajustar una parte del estado cuando cambie una _prop_, pero no todo el estado. -Este componente `List` recibe una lista de `items` como una prop y mantiene el elemento seleccionado en la variable de estado `selection`. Tu objetivo es resetear `selection` a `null` siempre que la prop `items` reciba un array diferente: +Este componente `List` recibe una lista de `items` como una prop y mantiene el _item_ seleccionado en la variable de estado `selection`. Deseas restablecer la variable de estado `selection` a `null` cada vez que la _prop_ `items` reciba un _array_ diferente: ```js {5-8} function List({ items }) { From 02c6cab869c1d9c28d983e866270976f6de03dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:08:40 -0300 Subject: [PATCH 072/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 34fcc878e..db3f574db 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -238,7 +238,7 @@ function List({ items }) { Cuando actualizas un componente durante el renderizado, React descarta el JSX devuelto y vuelve a intentar el renderizado de inmediato. Para evitar reintentos en cascada muy lentos, React solo te permite actualizar el estado del *mismo* componente durante el renderizado. Si intentas actualizar el estado de otro componente durante el renderizado, verás un error. Una condición como `items !== prevItems` es necesaria para evitar bucles. Puedes ajustar el estado de esta manera, pero cualquier otro efecto secundario (como cambios en el DOM o establecer tiempos de espera) debe mantenerse en los controladores de eventos o en Efectos para [mantener los componentes puros.](/learn/keeping-components-pure) -**Aunque este patrón es más eficiente que un Efecto, la mayoría de los componentes tampoco deberían necesitarlo.** No importa cómo lo hagas, ajustar el estado basado en las props u otro estado hace que tu flujo de datos sea más difícil de entender y depurar. Siempre verifica si puedes [resetear todo el estado con una key](#resetting-all-state-when-a-prop-changes) o [calcular todo durante el renderizado](#updating-state-based-on-props-or-state) en su lugar. Por ejemplo, en lugar de almacenar (y resetear) el *ítem* seleccionado, puedes almacenar el *ID del ítem seleccionado*: +**Aunque este patrón es más eficiente que un Efecto, la mayoría de los componentes tampoco lo necesitan.** Sin importar cómo lo hagas, ajustar el estado basado en _props_ u otro estado hace que el flujo de datos sea más difícil de entender y depurar. Siempre verifica si puedes [restablecer todo el estado con una _key_](#resetting-all-state-when-a-prop-changes) o [calcular todo durante el renderizado](#updating-state-based-on-props-or-state) en su lugar. Por ejemplo, en lugar de almacenar (y restablecer) el *item* seleccionado, puedes almacenar el *item ID* seleccionado: ```js {3-5} function List({ items }) { From a804fb9b1779ec362a7ec9592417e331502659f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:08:55 -0300 Subject: [PATCH 073/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index db3f574db..b9e74d488 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -244,7 +244,7 @@ Cuando actualizas un componente durante el renderizado, React descarta el JSX de function List({ items }) { const [isReverse, setIsReverse] = useState(false); const [selectedId, setSelectedId] = useState(null); - // ✅ Una mejor práctica: Calcular todo durante el renderizado + // ✅ Mejor: Calcular todo durante el renderizado. const selection = items.find(item => item.id === selectedId) ?? null; // ... } From 4c8877b11755126519d7906269cb01783d5254e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:09:09 -0300 Subject: [PATCH 074/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index b9e74d488..2b89e7c63 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -252,7 +252,7 @@ function List({ items }) { Ahora no hay necesidad de "ajustar" el estado en lo absoluto. Si el _item_ con el ID seleccionado está en la lista, permanecerá seleccionado. Si no lo está, la `selection` calculada durante el renderizado será `null` porque no se encontró ningún _item_ coincidente. Este comportamiento es diferente, pero se podría decir que es mejor porque la mayoría de los cambios en `items` preservan la selección. -### Compartir la lógica entre manejadores de eventos {/*sharing-logic-between-event-handlers*/} +### Compartir lógica entre controladores de eventos {/*sharing-logic-between-event-handlers*/} Supongamos que tienes una página de producto con dos botones (Comprar y Pagar) los cuales te permiten comprar ese producto. Quieres mostrar una notificación cada vez que el usuario pone el producto en el carrito. Llamar a `showNotification()` en los manejadores de clic de ambos botones se siente repetitivo, por lo que podrías estar tentado a colocar esta lógica en un Efecto: From 286e390dbafd3d261029ed47bc116175537d1bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:09:21 -0300 Subject: [PATCH 075/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 2b89e7c63..604d299e2 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -254,7 +254,7 @@ Ahora no hay necesidad de "ajustar" el estado en lo absoluto. Si el _item_ con e ### Compartir lógica entre controladores de eventos {/*sharing-logic-between-event-handlers*/} -Supongamos que tienes una página de producto con dos botones (Comprar y Pagar) los cuales te permiten comprar ese producto. Quieres mostrar una notificación cada vez que el usuario pone el producto en el carrito. Llamar a `showNotification()` en los manejadores de clic de ambos botones se siente repetitivo, por lo que podrías estar tentado a colocar esta lógica en un Efecto: +Supongamos que tienes una página de producto con dos botones (Comprar y Pagar) que permiten comprar ese producto. Deseas mostrar una notificación cada vez que el usuario agrega el producto al carrito. Llamar a `showNotification()` en los controladores de clic de ambos botones se siente repetitivo, por lo que podrías sentir la tentación de colocar esta lógica en un Efecto: ```js {2-7} function ProductPage({ product, addToCart }) { From df081326bcd1368e84a10bb8bfbfe50be94cd837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:09:35 -0300 Subject: [PATCH 076/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 604d299e2..2cd54fed4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -279,7 +279,7 @@ function ProductPage({ product, addToCart }) { Este Efecto es innecesario. Incluso es muy probable que cause errores. Por ejemplo, digamos que tu aplicación "recuerda" el carrito de compras entre recargas de la página. Si añades un producto al carrito una vez y refrescas la página, la notificación aparecerá de nuevo. Y seguirá apareciendo cada vez que refresques la página del producto. Esto se debe a que `product.isInCart` ya será `true` en la carga de la página, por lo que el Efecto anterior llamará a `showNotification()`. -**Cuando no estés seguro de si algún código debería estar en un Efecto o en un manejador de eventos, pregúntate *por qué* este código necesita ejecutarse. Usa Efectos solo para el código que debe ejecutarse *porque* el componente se mostró al usuario.** En este ejemplo, la notificación debería aparecer porque el usuario *presionó el botón*, ¡no porque se mostró la página! Elimina el Efecto y coloca la lógica compartida en una función llamada desde ambos manejadores de eventos: +**Cuando no estés seguro si algún código debe estar en un Efecto o en un controlador de eventos, pregúntate *por qué* este código necesita ejecutarse. Usa Efectos solo para el código que debe ejecutarse *porque* el componente fue mostrado al usuario.** En este ejemplo, la notificación debería aparecer porque el usuario *presionó el botón*, ¡no porque la página fue mostrada! Elimina el Efecto y coloca la lógica compartida en una función llamada desde ambos controladores de eventos: ```js {2-6,9,13} function ProductPage({ product, addToCart }) { From c801ecc2bb7e456c9b714657347790d5a2b2f0f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:09:47 -0300 Subject: [PATCH 077/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 2cd54fed4..afc51ffe3 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -277,7 +277,7 @@ function ProductPage({ product, addToCart }) { } ``` -Este Efecto es innecesario. Incluso es muy probable que cause errores. Por ejemplo, digamos que tu aplicación "recuerda" el carrito de compras entre recargas de la página. Si añades un producto al carrito una vez y refrescas la página, la notificación aparecerá de nuevo. Y seguirá apareciendo cada vez que refresques la página del producto. Esto se debe a que `product.isInCart` ya será `true` en la carga de la página, por lo que el Efecto anterior llamará a `showNotification()`. +Este Efecto es innecesario. También es muy probable que cause errores. Por ejemplo, supongamos que tu aplicación "recuerda" el carrito de compras entre las recargas de página. Si agregas un producto al carrito una vez y actualizas la página, la notificación aparecerá de nuevo. Seguirá apareciendo cada vez que actualices la página del producto. Esto se debe a que `product.isInCart` ya será `true` en la carga de la página, por lo que el Efecto anterior llamará a `showNotification()`. **Cuando no estés seguro si algún código debe estar en un Efecto o en un controlador de eventos, pregúntate *por qué* este código necesita ejecutarse. Usa Efectos solo para el código que debe ejecutarse *porque* el componente fue mostrado al usuario.** En este ejemplo, la notificación debería aparecer porque el usuario *presionó el botón*, ¡no porque la página fue mostrada! Elimina el Efecto y coloca la lógica compartida en una función llamada desde ambos controladores de eventos: From b08b3f9505a0f8499c4016d0e8797e5dc6193e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:10:02 -0300 Subject: [PATCH 078/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index afc51ffe3..081ae727c 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -283,7 +283,7 @@ Este Efecto es innecesario. También es muy probable que cause errores. Por ejem ```js {2-6,9,13} function ProductPage({ product, addToCart }) { - // ✅ Buena práctica: La lógica específica para eventos se llama desde los manejadores de eventos + // ✅ Correcto: La lógica específica del evento se llama desde los controladores de eventos. function buyProduct() { addToCart(product); showNotification(`Added ${product.name} to the shopping cart!`); From 55f9c71f4a30372e3102164c510e3a3f7fcb3a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:10:15 -0300 Subject: [PATCH 079/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 081ae727c..010f6b162 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -301,7 +301,7 @@ function ProductPage({ product, addToCart }) { } ``` -Esto tanto elimina el Efecto innecesario como corrige el error. +Esto no solo elimina el Efecto innecesario, sino que también corrige el error. ### Realizar una petición POST {/*sending-a-post-request*/} From 68b40abd79214f1f39a2fff0225f1b604c567f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:10:27 -0300 Subject: [PATCH 080/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 010f6b162..10d3baf84 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -305,7 +305,7 @@ Esto no solo elimina el Efecto innecesario, sino que también corrige el error. ### Realizar una petición POST {/*sending-a-post-request*/} -Este componente `Form` envía dos tipos de solicitudes POST. Envía un evento de analíticas cuando se monta. Por otra parte, cuando llenas el formulario y haces clic en el botón Enviar, enviará una solicitud POST al endpoint `/api/register`: +Este componente `Form` envía dos tipos de solicitudes POST. Envía un evento de analítica cuando se monta. Cuando completas el formulario y haces clic en el botón "Enviar", enviará una solicitud POST al punto final `/api/register`: ```js {5-8,10-16} function Form() { From 894c76f8b393612ebb53595e9fee7e20c354d332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:10:41 -0300 Subject: [PATCH 081/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 10d3baf84..ff1950812 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -303,7 +303,7 @@ function ProductPage({ product, addToCart }) { Esto no solo elimina el Efecto innecesario, sino que también corrige el error. -### Realizar una petición POST {/*sending-a-post-request*/} +### Enviar una solicitud POST {/*sending-a-post-request*/} Este componente `Form` envía dos tipos de solicitudes POST. Envía un evento de analítica cuando se monta. Cuando completas el formulario y haces clic en el botón "Enviar", enviará una solicitud POST al punto final `/api/register`: From 05e7839a38379c93dbe0e913599614ece406b48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:10:55 -0300 Subject: [PATCH 082/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index ff1950812..8daab8aff 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -317,7 +317,7 @@ function Form() { post('/analytics/event', { eventName: 'visit_form' }); }, []); - // 🔴 Evita: Lógica específica de evento dentro de un Efecto + // 🔴 Evitar: Lógica específica de evento dentro de un Efecto const [jsonToSubmit, setJsonToSubmit] = useState(null); useEffect(() => { if (jsonToSubmit !== null) { From f3512b163e5da73fb77c630b2b9de25e3bda6a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:11:10 -0300 Subject: [PATCH 083/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 8daab8aff..0eadf5959 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -312,7 +312,7 @@ function Form() { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); - // ✅ Buena práctica: Esta lógica debe ejecutarse porque el componente se mostró al usuario + // ✅ Correcto: Esta lógica debe ejecutarse porque el componente fue mostrado al usuario. useEffect(() => { post('/analytics/event', { eventName: 'visit_form' }); }, []); From 872f3deae15aaf4fe6d069f18689bd7b0ebf7f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:11:24 -0300 Subject: [PATCH 084/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 0eadf5959..e06e24376 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -333,7 +333,7 @@ function Form() { } ``` -Apliquemos el mismo criterio que en el ejemplo anterior. +Aplicaremos el mismo criterio que en el ejemplo anterior. La solicitud POST de analíticas debe permanecer en un Efecto. Esto es porque la _razón_ para enviar el evento de analíticas es que el formulario se mostró. (Se dispararía dos veces en desarrollo, pero [mira aquí](/learn/synchronizing-with-effects#sending-analytics) cómo lidiar con eso.) From f1d6101a42907002738ed2402b025c038f77d2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:11:37 -0300 Subject: [PATCH 085/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index e06e24376..6db633320 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -335,7 +335,7 @@ function Form() { Aplicaremos el mismo criterio que en el ejemplo anterior. -La solicitud POST de analíticas debe permanecer en un Efecto. Esto es porque la _razón_ para enviar el evento de analíticas es que el formulario se mostró. (Se dispararía dos veces en desarrollo, pero [mira aquí](/learn/synchronizing-with-effects#sending-analytics) cómo lidiar con eso.) +La solicitud POST de analítica debe permanecer en un Efecto. Esto se debe a que la _razón_ para enviar el evento de analítica es que el formulario se mostró. (Puede dispararse dos veces en desarrollo, pero [ver aquí](/learn/synchronizing-with-effects#sending-analytics) para aprender cómo manejarlo). Sin embargo, la solicitud POST a `/api/register` no es causada por el formulario siendo _mostrado al usuario_. Solo quieres enviar la solicitud en un momento específico en el tiempo: cuando el usuario presiona el botón. Solo debería ocurrir _en esa interacción en particular_. Elimina el segundo Efecto y mueve esa solicitud POST al manejador de eventos: From bb11a442ce75409a4a23283c58367736d9a181c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:11:49 -0300 Subject: [PATCH 086/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 6db633320..32b176e66 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -337,7 +337,7 @@ Aplicaremos el mismo criterio que en el ejemplo anterior. La solicitud POST de analítica debe permanecer en un Efecto. Esto se debe a que la _razón_ para enviar el evento de analítica es que el formulario se mostró. (Puede dispararse dos veces en desarrollo, pero [ver aquí](/learn/synchronizing-with-effects#sending-analytics) para aprender cómo manejarlo). -Sin embargo, la solicitud POST a `/api/register` no es causada por el formulario siendo _mostrado al usuario_. Solo quieres enviar la solicitud en un momento específico en el tiempo: cuando el usuario presiona el botón. Solo debería ocurrir _en esa interacción en particular_. Elimina el segundo Efecto y mueve esa solicitud POST al manejador de eventos: +Sin embargo, la solicitud POST a `/api/register` no es causada por el formulario siendo _mostrado_. Solo deseas enviar la solicitud en un momento específico: cuando el usuario presiona el botón. Debería suceder solo durante _esa interacción particular_. Elimina el segundo Efecto y coloca esa solicitud POST dentro del controlador de eventos: ```js {12-13} function Form() { From 55d6280f704bbc94f93842b9b89a804079b32668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:12:02 -0300 Subject: [PATCH 087/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 32b176e66..0e5cafe03 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -344,7 +344,7 @@ function Form() { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); - // ✅ Buena práctica: Esta lógica se ejecuta porque el componente se mostró al usuario + // ✅ Correcto: Esta lógica se ejecuta porque el componente fue mostrado al usuario. useEffect(() => { post('/analytics/event', { eventName: 'visit_form' }); }, []); From 0f64024699568689b16bae03939d4921ec544c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:12:15 -0300 Subject: [PATCH 088/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 0e5cafe03..95d4e1bb0 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -351,7 +351,7 @@ function Form() { function handleSubmit(e) { e.preventDefault(); - // ✅ Buena práctica: La lógica para el evento se ejecuta en un manejador de eventos + // ✅ Correcto: La lógica específica del evento se encuentra en el controlador de eventos. post('/api/register', { firstName, lastName }); } // ... From 00ad195ea7e891396250246365ac13532905ea28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:12:45 -0300 Subject: [PATCH 089/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 95d4e1bb0..e25e10392 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -358,7 +358,7 @@ function Form() { } ``` -Cuando estaás por decidir si poner alguna lógica en un manejador de eventos o un Efecto, la pregunta principal que debes responder es _qué tipo de lógica_ es desde la perspectiva del usuario. Si esta lógica es causada por una interacción en particular, mantenla en el manejador de eventos. Si es causada porque el usuario _ve_ el componente en la pantalla, mantenla en el Efecto. +Cuando decidas si colocar cierta lógica en un controlador de eventos o en un Efecto, la pregunta principal que debes responder es _qué tipo de lógica_ es desde la perspectiva del usuario. Si esta lógica es causada por una interacción particular, mantenla en el controlador de eventos. Si es causada por el usuario _visualizando_ el componente en la pantalla, mantenla en el Efecto. ### Cadenas de cálculos {/*chains-of-computations*/} From e28afb8e5a7da95e93bf927a23f1dce619a6e27e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:13:07 -0300 Subject: [PATCH 090/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index e25e10392..47be364a3 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -362,7 +362,7 @@ Cuando decidas si colocar cierta lógica en un controlador de eventos o en un Ef ### Cadenas de cálculos {/*chains-of-computations*/} -A veces podrías sentirte tentado a encadenar Efectos que ajustan una pieza de estado basada en otro estado: +A veces podrías sentirte tentado a encadenar Efectos que ajustan cada uno una parte del estado basándose en otro estado: ```js {7-29} function Game() { From f2f819021c3b6bdd35013779e8e38e8bf87d8ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:13:21 -0300 Subject: [PATCH 091/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 47be364a3..809aecfb3 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -371,7 +371,7 @@ function Game() { const [round, setRound] = useState(1); const [isGameOver, setIsGameOver] = useState(false); - // 🔴 Evitar: Cadenas de Efectos que ajustan el estado solo para activarse entre sí + // 🔴 Evitar: Cadenas de Efectos que ajustan el estado solo para activarse entre sí. useEffect(() => { if (card !== null && card.gold) { setGoldCardCount(c => c + 1); From 118662ebc3a039620bacc7a69868a45ed1ba0112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:13:36 -0300 Subject: [PATCH 092/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 809aecfb3..bc0eb69f5 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -408,7 +408,7 @@ function Game() { Hay dos problemas con este código. -Un problema es que es muy ineficiente: el componente (y sus hijos) tienen que volver a renderizarse entre cada llamada a un actualizador `set-` en la cadena. En el ejemplo anterior, en el peor de los casos (`setCard` → render → `setGoldCardCount` → render → `setRound` → render → `setIsGameOver` → render) hay tres renderizaciones innecesarias del árbol hacia debajo. +Un problema es que es muy ineficiente: el componente (y su hijo) deben volver a renderizarse entre cada llamada a `set` en la cadena. En el ejemplo anterior, en el peor caso (`setCard` → renderizado → `setGoldCardCount` → renderizado → `setRound` → renderizado → `setIsGameOver` → renderizado), hay tres renderizados innecesarios del árbol hacia abajo. Incluso si no fuera lento, a medida que tu código evoluciona, te encontrarás con casos en los que la "cadena" que escribiste no se ajusta a los nuevos requisitos. Imagina que estás añadiendo una forma de repasar el historial de movimientos del juego. Lo harías actualizando cada variable de estado a un valor del pasado. Sin embargo, establecer el estado `card` a un valor del pasado desencadenaría de nuevo la cadena de Efectos y cambiaría los datos que estás mostrando. Este tipo de código es a menudo rígido y frágil. From e70a00a1a46cbfd2057f37e6590db1428b8762a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:13:54 -0300 Subject: [PATCH 093/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index bc0eb69f5..46206d4e3 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -410,7 +410,7 @@ Hay dos problemas con este código. Un problema es que es muy ineficiente: el componente (y su hijo) deben volver a renderizarse entre cada llamada a `set` en la cadena. En el ejemplo anterior, en el peor caso (`setCard` → renderizado → `setGoldCardCount` → renderizado → `setRound` → renderizado → `setIsGameOver` → renderizado), hay tres renderizados innecesarios del árbol hacia abajo. -Incluso si no fuera lento, a medida que tu código evoluciona, te encontrarás con casos en los que la "cadena" que escribiste no se ajusta a los nuevos requisitos. Imagina que estás añadiendo una forma de repasar el historial de movimientos del juego. Lo harías actualizando cada variable de estado a un valor del pasado. Sin embargo, establecer el estado `card` a un valor del pasado desencadenaría de nuevo la cadena de Efectos y cambiaría los datos que estás mostrando. Este tipo de código es a menudo rígido y frágil. +Incluso si no fuera lento, a medida que evoluciona tu código, te encontrarás con casos en los que la "cadena" que escribiste no se ajusta a los nuevos requisitos. Imagina que estás agregando una forma de recorrer el historial de los movimientos del juego. Lo harías actualizando cada variable de estado a un valor del pasado. Sin embargo, establecer el estado de `card` a un valor del pasado volvería a activar la cadena de Efectos y cambiaría los datos que estás mostrando. Este tipo de código suele ser rígido y frágil. En este caso, es mejor calcular lo que puedas durante la renderización, y ajustar el estado en el manejador de eventos: From b1324152ccd86d7d88b95b41573f3f7135752072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:15:17 -0300 Subject: [PATCH 094/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 46206d4e3..fe504a1b2 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -412,7 +412,7 @@ Un problema es que es muy ineficiente: el componente (y su hijo) deben volver a Incluso si no fuera lento, a medida que evoluciona tu código, te encontrarás con casos en los que la "cadena" que escribiste no se ajusta a los nuevos requisitos. Imagina que estás agregando una forma de recorrer el historial de los movimientos del juego. Lo harías actualizando cada variable de estado a un valor del pasado. Sin embargo, establecer el estado de `card` a un valor del pasado volvería a activar la cadena de Efectos y cambiaría los datos que estás mostrando. Este tipo de código suele ser rígido y frágil. -En este caso, es mejor calcular lo que puedas durante la renderización, y ajustar el estado en el manejador de eventos: +En este caso, es mejor calcular lo que puedas durante el proceso de renderizado y ajustar el estado en el controlador de eventos: ```js {6-7,14-26} function Game() { From 56dff9121999feae5a45c798adc3d291b4a382f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:15:29 -0300 Subject: [PATCH 095/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index fe504a1b2..7fef8f693 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -420,7 +420,7 @@ function Game() { const [goldCardCount, setGoldCardCount] = useState(0); const [round, setRound] = useState(1); - // ✅ Calcula lo que puedas durante la renderización + // ✅ Calcula lo que puedas durante el proceso de renderizado. const isGameOver = round > 5; function handlePlaceCard(nextCard) { From a7c2dfc83d31b9343fc8d2e1c0021d5bc9a81211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:15:40 -0300 Subject: [PATCH 096/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 7fef8f693..d84dc45e8 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -428,7 +428,7 @@ function Game() { throw Error('Game already ended.'); } - // ✅ Calcula todo el siguiente estado en el manejador de eventos + // ✅ Calcula todo el próximo estado en el controlador de eventos. setCard(nextCard); if (nextCard.gold) { if (goldCardCount <= 3) { From 68e546f201913bf5d377c0431977382807a19a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:15:51 -0300 Subject: [PATCH 097/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index d84dc45e8..aba971698 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -507,7 +507,7 @@ El código en el nivel superior se ejecuta una vez cuando se importa tu componen ### Notificar a los componentes padre sobre cambios de estado {/*notifying-parent-components-about-state-changes*/} -Digamos que estás escribiendo un componente `Toggle` con un estado interno `isOn` que puede ser `true` o `false`. Hay varias formas diferentes de cambiarlo (haciendo clic o arrastrando). Quieres notificar al componente padre cada vez que el estado interno de `Toggle` cambia, así que expones un evento `onChange` y lo llamas desde un Efecto: +Digamos que estás escribiendo un componente `Toggle` con un estado interno `isOn` que puede ser `true` o `false`. Hay algunas formas diferentes de alternarlo (haciendo clic o arrastrando). Quieres notificar al componente padre cada vez que el estado interno del `Toggle` cambie, por lo que expones un evento `onChange` y lo llamas desde un Efecto: ```js {4-7} function Toggle({ onChange }) { From 9ac46408704d21cb0f802619e3ccfbb78864f6ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:16:01 -0300 Subject: [PATCH 098/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index aba971698..02baae3b5 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -513,7 +513,7 @@ Digamos que estás escribiendo un componente `Toggle` con un estado interno `isO function Toggle({ onChange }) { const [isOn, setIsOn] = useState(false); - // 🔴 Evitar: El manejador onChange se ejecuta demasiado tarde + // 🔴 Evitar: El controlador `onChange` se ejecuta demasiado tarde. useEffect(() => { onChange(isOn); }, [isOn, onChange]) From e95248654e5f59618108fc39b6990e44fa54796b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:16:12 -0300 Subject: [PATCH 099/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 02baae3b5..0754eb17f 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -534,7 +534,7 @@ function Toggle({ onChange }) { } ``` -Como antes, esto no es ideal. El `Toggle` actualiza su estado primero, y React actualiza la pantalla. Luego React ejecuta el Efecto, que llama a la función `onChange` pasada desde un componente padre. Ahora el componente padre actualizará su propio estado, iniciando otro proceso de renderizado. Sería mejor hacer todo en un solo paso. +Como mencionamos anteriormente, esto no es ideal. El `Toggle` actualiza su estado primero, y React actualiza la pantalla. Luego, React ejecuta el Efecto, que llama a la función `onChange` pasada desde un componente padre. Ahora el componente padre actualizará su propio estado, iniciando otro proceso de renderizado. Sería mejor hacer todo en un solo paso. Elimina el Efecto y en su lugar actualiza el estado de *ambos* componentes dentro del mismo manejador de eventos: From f7adf2dedb020f59418c2c6fd5cd40c649082361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:16:24 -0300 Subject: [PATCH 100/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 0754eb17f..8aeabf421 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -536,7 +536,7 @@ function Toggle({ onChange }) { Como mencionamos anteriormente, esto no es ideal. El `Toggle` actualiza su estado primero, y React actualiza la pantalla. Luego, React ejecuta el Efecto, que llama a la función `onChange` pasada desde un componente padre. Ahora el componente padre actualizará su propio estado, iniciando otro proceso de renderizado. Sería mejor hacer todo en un solo paso. -Elimina el Efecto y en su lugar actualiza el estado de *ambos* componentes dentro del mismo manejador de eventos: +Elimina el Efecto y, en su lugar, actualiza el estado de *ambos* componentes dentro del mismo controlador de eventos: ```js {5-7,11,16,18} function Toggle({ onChange }) { From 11cbb41a7c874e4c7eaed22be084cd6f56a46e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:16:35 -0300 Subject: [PATCH 101/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 8aeabf421..3bd63daa2 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -543,7 +543,7 @@ function Toggle({ onChange }) { const [isOn, setIsOn] = useState(false); function updateToggle(nextIsOn) { - // ✅ Bien: Realiza todas las actualizaciones durante el evento que las causó + // ✅ Correcto: Realiza todas las actualizaciones durante el evento que las causó setIsOn(nextIsOn); onChange(nextIsOn); } From 839f964988f313c33840a007031f3e00fbbe78b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:16:46 -0300 Subject: [PATCH 102/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 3bd63daa2..aedd7a43c 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -564,7 +564,7 @@ function Toggle({ onChange }) { } ``` -Con este enfoque, tanto el componente `Toggle` como su componente padre actualizan su estado durante el evento. React [agrupa las actualizaciones](/learn/queueing-a-series-of-state-updates) de diferentes componentes, por lo que sólo habrá un paso de renderizado. +Con este enfoque, tanto el componente `Toggle` como su componente padre actualizan su estado durante el evento. React [agrupa las actualizaciones](/learn/queueing-a-series-of-state-updates) de diferentes componentes juntas, por lo que solo habrá un pase de renderizado. También podrías eliminar el estado por completo, y en su lugar recibir `isOn` del componente padre: From 49bba88ef8a14ac4fe1a6f486aee4619e9c426ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:16:59 -0300 Subject: [PATCH 103/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index aedd7a43c..d5ceba363 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -566,7 +566,7 @@ function Toggle({ onChange }) { Con este enfoque, tanto el componente `Toggle` como su componente padre actualizan su estado durante el evento. React [agrupa las actualizaciones](/learn/queueing-a-series-of-state-updates) de diferentes componentes juntas, por lo que solo habrá un pase de renderizado. -También podrías eliminar el estado por completo, y en su lugar recibir `isOn` del componente padre: +También podrías eliminar completamente el estado y, en su lugar, recibir `isOn` desde el componente padre: ```js {1,2} // ✅ También está bien: el componente está completamente controlado por su padre From e928ac85603a8772370389b70526704578446dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:17:11 -0300 Subject: [PATCH 104/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index d5ceba363..f4fb27539 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -569,7 +569,7 @@ Con este enfoque, tanto el componente `Toggle` como su componente padre actualiz También podrías eliminar completamente el estado y, en su lugar, recibir `isOn` desde el componente padre: ```js {1,2} -// ✅ También está bien: el componente está completamente controlado por su padre +// ✅ También correcto: el componente está completamente controlado por su padre function Toggle({ isOn, onChange }) { function handleClick() { onChange(!isOn); From 4e1406ed23d0768e9e18b454d175d9c48553605b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:38:16 -0300 Subject: [PATCH 105/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index f4fb27539..a184aaca6 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -747,7 +747,7 @@ function SearchResults({ query }) { } ``` -Esto asegura que cuando tu Efecto carga datos, todas las respuestas excepto la última solicitada serán ignoradas. +Esto asegura que cuando tu Efecto obtiene datos, todas las respuestas excepto la última solicitada serán ignoradas. Manejar las condiciones de carrera no es la única dificultad al implementar la carga de datos. También podrías querer pensar en almacenar en caché las respuestas (para que el usuario pueda hacer clic en "Atrás" y ver la pantalla anterior instantáneamente), en cómo obtener datos en el servidor (para que el HTML inicial renderizado por el servidor contenga el contenido obtenido en lugar de un spinner), y en cómo evitar cascadas de red (para que un hijo pueda cargar datos sin esperar a cada padre). From ad52ab2b72e481aa4095984262d9fdb50e0832f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:43:59 -0300 Subject: [PATCH 106/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index a184aaca6..be2f392aa 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -587,7 +587,7 @@ function Toggle({ isOn, onChange }) { } ``` -["Elevar el estado"](/learn/sharing-state-between-components) te permite que el componente padre controle completamente el `Toggle` cambiando el estado propio del padre. Esto significa que el componente padre tendrá que contener más lógica, pero habrá menos estado en general de qué preocuparse. ¡Cada vez que intentes mantener dos variables de estado diferentes sincronizadas, intenta elevar el estado en su lugar! +["Levantar el estado"](/learn/sharing-state-between-components)" permite que el componente padre controle completamente el `Toggle` al alternar el estado del propio componente padre. Esto significa que el componente padre deberá contener más lógica, pero en general habrá menos estado con el que preocuparse. Siempre que intentes mantener sincronizadas dos variables de estado diferentes, ¡intenta levantar el estado en su lugar! ### Pasar datos al componente padre {/*passing-data-to-the-parent*/} From 3f9ad1085fefbd736dd8913c0c3aa22a7858910d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:44:10 -0300 Subject: [PATCH 107/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index be2f392aa..ec571562c 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -591,7 +591,7 @@ function Toggle({ isOn, onChange }) { ### Pasar datos al componente padre {/*passing-data-to-the-parent*/} -Este componente `Child` carga algunos datos y luego los pasa al componente `Parent` en un Efecto: +Este componente `Child` obtiene algunos datos y luego los pasa al componente `Parent` en un Efecto: ```js {9-14} function Parent() { From 6b18fd4677057e85375e2e0dc959799d1ea9bbf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:44:23 -0300 Subject: [PATCH 108/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index ec571562c..8d023b249 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -612,7 +612,7 @@ function Child({ onFetched }) { } ``` -En React, los datos fluyen de los componentes padres a sus hijos. Cuando ves algo incorrecto en la pantalla, puedes rastrear de dónde viene la información subiendo la cadena de componentes hasta que encuentres qué componente pasa la prop incorrecta o tiene el estado incorrecto. Cuando los componentes hijos actualizan el estado de sus componentes padres en Efectos, el flujo de datos se vuelve muy difícil de rastrear. Como tanto el hijo como el padre necesitan los mismos datos, deja que el componente padre recupere esos datos, y *pásalos hacia abajo* al hijo en su lugar: +En React, los datos fluyen desde los componentes padres hacia sus hijos. Cuando ves algo incorrecto en la pantalla, puedes rastrear de dónde proviene la información siguiendo la cadena de componentes hacia arriba hasta encontrar qué componente pasa la _prop_ incorrecta o tiene el estado incorrecto. Cuando los componentes hijos actualizan el estado de sus componentes padres en Efectos, el flujo de datos se vuelve muy difícil de rastrear. Dado que tanto el hijo como el padre necesitan los mismos datos, permite que el componente padre obtenga esos datos y los *pase hacia abajo* al hijo en su lugar: ```js {4-5} function Parent() { From e345b59398f2c824c6d343326d42c743525453f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:44:34 -0300 Subject: [PATCH 109/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 8d023b249..b82d89d3d 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -618,7 +618,7 @@ En React, los datos fluyen desde los componentes padres hacia sus hijos. Cuando function Parent() { const data = useSomeAPI(); // ... - // ✅ Buena práctica: Pasar los datos desde padres a hijos + // ✅ Correcto: Pasando datos hacia abajo al hijo. return ; } From 93f35dc0017119a6eabce7b3e2ba2fa9085fcc5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:44:46 -0300 Subject: [PATCH 110/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index b82d89d3d..20f1c3e43 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -629,7 +629,7 @@ function Child({ data }) { Esto es más sencillo y mantiene el flujo de datos predecible: los datos fluyen hacia abajo desde el padre al hijo. -### Suscribirse a una fuente de datos externa {/*subscribing-to-an-external-store*/} +### Suscripción a un almacén externo {/*subscribing-to-an-external-store*/} A veces, tus componentes pueden necesitar suscribirse a algunos datos fuera del estado de React. Estos datos podrían provenir de una biblioteca de terceros o de una API incorporada en el navegador. Como estos datos pueden cambiar sin que React lo sepa, necesitas suscribir manualmente tus componentes a ellos. Esto se hace a menudo con un Efecto, por ejemplo: From b5cefa77d127fd7fd61dfec83894770b7fe0d629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:44:58 -0300 Subject: [PATCH 111/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 20f1c3e43..b81b3ca12 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -631,7 +631,7 @@ Esto es más sencillo y mantiene el flujo de datos predecible: los datos fluyen ### Suscripción a un almacén externo {/*subscribing-to-an-external-store*/} -A veces, tus componentes pueden necesitar suscribirse a algunos datos fuera del estado de React. Estos datos podrían provenir de una biblioteca de terceros o de una API incorporada en el navegador. Como estos datos pueden cambiar sin que React lo sepa, necesitas suscribir manualmente tus componentes a ellos. Esto se hace a menudo con un Efecto, por ejemplo: +A veces, tus componentes pueden necesitar suscribirse a algunos datos fuera del estado de React. Estos datos podrían provenir de una biblioteca de terceros o de una API incorporada en el navegador. Dado que estos datos pueden cambiar sin que React lo sepa, es necesario suscribir manualmente tus componentes a ellos. Esto se hace frecuentemente con un Efecto, por ejemplo: ```js {2-17} function useOnlineStatus() { From fbd3273dacbb4f4a578a26a7a489a6d131b2ecfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:45:09 -0300 Subject: [PATCH 112/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index b81b3ca12..e71e43357 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -627,7 +627,7 @@ function Child({ data }) { } ``` -Esto es más sencillo y mantiene el flujo de datos predecible: los datos fluyen hacia abajo desde el padre al hijo. +Esto es más simple y mantiene el flujo de datos predecible: los datos fluyen hacia abajo desde el padre hacia el hijo. ### Suscripción a un almacén externo {/*subscribing-to-an-external-store*/} From 0a9339e706915b1f96ad5d972fec73de1c641b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:45:32 -0300 Subject: [PATCH 113/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index e71e43357..4d6da72bd 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -635,7 +635,7 @@ A veces, tus componentes pueden necesitar suscribirse a algunos datos fuera del ```js {2-17} function useOnlineStatus() { - // No ideal: Suscripción manual en un Efecto + // No es lo ideal: Suscripción manual a un almacén en un Efecto. const [isOnline, setIsOnline] = useState(true); useEffect(() => { function updateState() { From 26289bd2aa292d9aa59820409b1cb9248e118cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:45:42 -0300 Subject: [PATCH 114/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 4d6da72bd..0cb50e716 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -660,7 +660,7 @@ function ChatIndicator() { } ``` -Aquí, el componente se suscribe a una fuente de datos externa (en este caso, la API `navigator.onLine` del navegador). Dado que esta API no existe en el servidor (por lo que no puede usarse para el HTML inicial), inicialmente el estado se establece en `true`. Siempre que el valor de esa fuente de datos cambia en el navegador, el componente actualiza su estado. +Aquí, el componente se suscribe a un almacén de datos externos (en este caso, la API `navigator.onLine` del navegador). Dado que esta API no existe en el servidor (por lo que no se puede utilizar para el HTML inicial), inicialmente el estado se establece en `true`. Cada vez que el valor de ese almacén de datos cambia en el navegador, el componente actualiza su estado. Aunque es común usar Efectos para esto, React tiene un Hook diseñado específicamente para suscribirse a una fuente externa que se prefiere en su lugar. Elimina el Efecto y reemplázalo con una llamada al Hook de React [`useSyncExternalStore`](/reference/react/useSyncExternalStore): From 7bc03f3a031fd0a72942f2110dd03200398decc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:45:53 -0300 Subject: [PATCH 115/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 0cb50e716..2e2630489 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -662,7 +662,7 @@ function ChatIndicator() { Aquí, el componente se suscribe a un almacén de datos externos (en este caso, la API `navigator.onLine` del navegador). Dado que esta API no existe en el servidor (por lo que no se puede utilizar para el HTML inicial), inicialmente el estado se establece en `true`. Cada vez que el valor de ese almacén de datos cambia en el navegador, el componente actualiza su estado. -Aunque es común usar Efectos para esto, React tiene un Hook diseñado específicamente para suscribirse a una fuente externa que se prefiere en su lugar. Elimina el Efecto y reemplázalo con una llamada al Hook de React [`useSyncExternalStore`](/reference/react/useSyncExternalStore): +Aunque es común utilizar Efectos para esto, React tiene un Hook específicamente diseñado para suscribirse a un almacén de datos externos que se prefiere en su lugar. Elimina el Efecto y reemplázalo con una llamada a [`useSyncExternalStore`](/reference/react/useSyncExternalStore): ```js {11-16} function subscribe(callback) { From f1603e30642165605646a0f7e0c45343c4817ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:46:06 -0300 Subject: [PATCH 116/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 2e2630489..5e3269a80 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -675,7 +675,7 @@ function subscribe(callback) { } function useOnlineStatus() { - // ✅ Buena práctica: Suscribirse a una fuente externa con un Hook integrado + // ✅ Bien: Suscribirse a un almacén externo con un Hook incorporado. return useSyncExternalStore( subscribe, // React no volverá a suscribirse mientras pases la misma función () => navigator.onLine, // Acá va el cómo obtener el valor en el cliente From b7715f1ba33ed6c402ec4fbcbf3955142a7ed69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:46:15 -0300 Subject: [PATCH 117/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 5e3269a80..1a419b7f1 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -678,7 +678,7 @@ function useOnlineStatus() { // ✅ Bien: Suscribirse a un almacén externo con un Hook incorporado. return useSyncExternalStore( subscribe, // React no volverá a suscribirse mientras pases la misma función - () => navigator.onLine, // Acá va el cómo obtener el valor en el cliente + () => navigator.onLine, // Cómo obtener el valor en el cliente. () => true // Acá va el cómo obtener el valor en el servidor ); } From ef46755478a79c629b60c2bbc678c82e4a101db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:46:25 -0300 Subject: [PATCH 118/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 1a419b7f1..240f15e63 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -677,7 +677,7 @@ function subscribe(callback) { function useOnlineStatus() { // ✅ Bien: Suscribirse a un almacén externo con un Hook incorporado. return useSyncExternalStore( - subscribe, // React no volverá a suscribirse mientras pases la misma función + subscribe, // React no volverá a suscribirse mientras pases la misma función. () => navigator.onLine, // Cómo obtener el valor en el cliente. () => true // Acá va el cómo obtener el valor en el servidor ); From 1d46a40c682880aac4a7771104c256501436e065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:46:36 -0300 Subject: [PATCH 119/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 240f15e63..967e79fd1 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -679,7 +679,7 @@ function useOnlineStatus() { return useSyncExternalStore( subscribe, // React no volverá a suscribirse mientras pases la misma función. () => navigator.onLine, // Cómo obtener el valor en el cliente. - () => true // Acá va el cómo obtener el valor en el servidor + () => true // Cómo obtener el valor en el servidor. ); } From 34e521d8bb8f6b70820b147fc89df7e37850f6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:46:46 -0300 Subject: [PATCH 120/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 967e79fd1..8d40d6c9c 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -689,7 +689,7 @@ function ChatIndicator() { } ``` -Este enfoque es menos propenso a errores que sincronizar manualmente datos mutables al estado de React con un Efecto. Generalmente, escribirás un Hook personalizado como `useOnlineStatus()` anteriormente para que no debas repetir este código en los componentes individuales. [Lee más sobre cómo suscribirte a fuentes externas desde componentes de React.](/reference/react/useSyncExternalStore) +Este enfoque es menos propenso a errores que la sincronización manual de datos mutables al estado de React con un Efecto. Típicamente, escribirás un Hook personalizado como `useOnlineStatus()` como se muestra arriba, para que no necesites repetir este código en los componentes individuales. [Lee más sobre cómo suscribirte a almacenes externos desde componentes React.](/reference/react/useSyncExternalStore) ### Cargar datos {/*fetching-data*/} From 14526e6849a9ce74f416b20302017bf062bd71d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:46:57 -0300 Subject: [PATCH 121/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 8d40d6c9c..4f88de944 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -691,7 +691,7 @@ function ChatIndicator() { Este enfoque es menos propenso a errores que la sincronización manual de datos mutables al estado de React con un Efecto. Típicamente, escribirás un Hook personalizado como `useOnlineStatus()` como se muestra arriba, para que no necesites repetir este código en los componentes individuales. [Lee más sobre cómo suscribirte a almacenes externos desde componentes React.](/reference/react/useSyncExternalStore) -### Cargar datos {/*fetching-data*/} +### Obtención de datos {/*fetching-data*/} Muchas aplicaciones usan Efectos para iniciar la carga de datos. Es bastante común escribir un Efecto de carga de datos como este: From f6af07f30304fcf9f6db933aa872cb563b2d802e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:47:34 -0300 Subject: [PATCH 122/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 4f88de944..3c2c05e0a 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -693,7 +693,7 @@ Este enfoque es menos propenso a errores que la sincronización manual de datos ### Obtención de datos {/*fetching-data*/} -Muchas aplicaciones usan Efectos para iniciar la carga de datos. Es bastante común escribir un Efecto de carga de datos como este: +Muchas aplicaciones utilizan Efectos para iniciar la obtención de datos. Es bastante común escribir un Efecto para obtener datos de esta manera: ```js {5-10} function SearchResults({ query }) { From 863ee2dc847ce279dcfc8636b85bd60629116ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:47:51 -0300 Subject: [PATCH 123/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 3c2c05e0a..78f23f836 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -701,7 +701,7 @@ function SearchResults({ query }) { const [page, setPage] = useState(1); useEffect(() => { - // 🔴 Evita: Obtener datos sin lógica de limpieza + // 🔴 Evitar: Obtener datos sin lógica de limpieza. fetchResults(query, page).then(json => { setResults(json); }); From 81af4d74da8cbc35bbdbd9d36e87be1856f6c3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:48:01 -0300 Subject: [PATCH 124/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 78f23f836..0a1b568a4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -714,7 +714,7 @@ function SearchResults({ query }) { } ``` -No necesitas mover esta carga de datos a un manejador de eventos. +No *necesitas* mover esta solicitud (fetch) a un controlador de eventos. Esto puede parecer una contradicción con los ejemplos anteriores donde necesitabas poner la lógica en los manejadores de eventos. Sin embargo, considera que no es *el evento de escritura* el que es la razón principal para cargar datos. Las entradas de búsqueda a menudo se pre-rellenan desde la URL, y el usuario puede navegar hacia atrás y hacia adelante sin tocar la entrada de texto. From 48af9e7f18bbc8e44fd6d68b8e3ac1838adf3460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:48:20 -0300 Subject: [PATCH 125/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 0a1b568a4..1884853b4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -716,7 +716,7 @@ function SearchResults({ query }) { No *necesitas* mover esta solicitud (fetch) a un controlador de eventos. -Esto puede parecer una contradicción con los ejemplos anteriores donde necesitabas poner la lógica en los manejadores de eventos. Sin embargo, considera que no es *el evento de escritura* el que es la razón principal para cargar datos. Las entradas de búsqueda a menudo se pre-rellenan desde la URL, y el usuario puede navegar hacia atrás y hacia adelante sin tocar la entrada de texto. +Esto puede parecer una contradicción con los ejemplos anteriores donde necesitabas poner la lógica en los controladores de eventos. Sin embargo, considera que no es *el evento de escritura* la razón principal para realizar la solicitud (_fetch_). Los campos de búsqueda a menudo se precargan desde la URL, y el usuario podría navegar hacia atrás y adelante sin tocar el campo de entrada. No importa de dónde vengan `page` y `query`. Mientras este componente sea visible, querrás mantener los `results` [sincronizados](/learn/synchronizing-with-effects) con los datos de la red para la `page` y `query` actuales. Por eso es un Efecto. From 32af906b1c2fb20e3f0daa1f7aafa4d3df4f33d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:48:33 -0300 Subject: [PATCH 126/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 1884853b4..7ed56e4f0 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -718,7 +718,7 @@ No *necesitas* mover esta solicitud (fetch) a un controlador de eventos. Esto puede parecer una contradicción con los ejemplos anteriores donde necesitabas poner la lógica en los controladores de eventos. Sin embargo, considera que no es *el evento de escritura* la razón principal para realizar la solicitud (_fetch_). Los campos de búsqueda a menudo se precargan desde la URL, y el usuario podría navegar hacia atrás y adelante sin tocar el campo de entrada. -No importa de dónde vengan `page` y `query`. Mientras este componente sea visible, querrás mantener los `results` [sincronizados](/learn/synchronizing-with-effects) con los datos de la red para la `page` y `query` actuales. Por eso es un Efecto. +No importa de dónde provengan `page` y `query`. Mientras este componente sea visible, deseas mantener `results` [sincronizado](/learn/synchronizing-with-effects) con los datos de la red para la `page` y `query` actuales. Por eso es un Efecto. Sin embargo, el código anterior tiene un error. Imagina que escribes "hola" rápidamente. Entonces la `query` cambiará de "h", a "ho", "hol", y "hola". Esto iniciará búsquedas separadas, pero no hay garantía sobre el orden en que llegarán las respuestas. Por ejemplo, la respuesta "hol" puede llegar *después* de la respuesta "hola". Como "hol" llamará a `setResults()` al final, estarás mostrando los resultados de búsqueda incorrectos. Esto se llama una ["condición de carrera"](https://es.wikipedia.org/wiki/Condición_de_carrera): dos solicitudes diferentes "compitieron" entre sí y llegaron en un orden diferente al que esperabas. From cb2cfb11192a6e1b3ceb0bb05f69c5cf90f80f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:48:41 -0300 Subject: [PATCH 127/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 7ed56e4f0..b0fdafb86 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -751,7 +751,7 @@ Esto asegura que cuando tu Efecto obtiene datos, todas las respuestas excepto la Manejar las condiciones de carrera no es la única dificultad al implementar la carga de datos. También podrías querer pensar en almacenar en caché las respuestas (para que el usuario pueda hacer clic en "Atrás" y ver la pantalla anterior instantáneamente), en cómo obtener datos en el servidor (para que el HTML inicial renderizado por el servidor contenga el contenido obtenido en lugar de un spinner), y en cómo evitar cascadas de red (para que un hijo pueda cargar datos sin esperar a cada padre). -**Estos problemas se aplican a cualquier biblioteca de interfaz de usuario, no solo a React. Resolverlos no es trivial, por lo que los [frameworks](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos proporcionan mecanismos de carga de datos integrados más eficientes que la carga de datos con Efectos.** +**Estos problemas aplican a cualquier biblioteca de UI, no solo a React. Resolverlos no es trivial, por eso los [frameworks](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos ofrecen mecanismos incorporados más eficientes de obtención de datos que obtener datos en Efectos.** Si no usas un framework (y no quieres construir el tuyo propio) pero te gustaría hacer que la carga de datos desde Efectos sea más ergonómica, considera extraer tu lógica de obtención a un Hook personalizado como en el siguiente ejemplo: From c8f0dc69d0959c9343d861c8189f385fd19073a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:48:52 -0300 Subject: [PATCH 128/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index b0fdafb86..b80d2a5ad 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -749,7 +749,7 @@ function SearchResults({ query }) { Esto asegura que cuando tu Efecto obtiene datos, todas las respuestas excepto la última solicitada serán ignoradas. -Manejar las condiciones de carrera no es la única dificultad al implementar la carga de datos. También podrías querer pensar en almacenar en caché las respuestas (para que el usuario pueda hacer clic en "Atrás" y ver la pantalla anterior instantáneamente), en cómo obtener datos en el servidor (para que el HTML inicial renderizado por el servidor contenga el contenido obtenido en lugar de un spinner), y en cómo evitar cascadas de red (para que un hijo pueda cargar datos sin esperar a cada padre). +Manejar las condiciones de carrera no es la única dificultad al implementar la obtención de datos. También podrías considerar el almacenamiento en caché de las respuestas (para que el usuario pueda hacer clic en "Atrás" y ver la pantalla anterior instantáneamente), cómo obtener datos en el servidor (para que el HTML renderizado inicialmente por el servidor contenga el contenido obtenido en lugar de un indicador de carga (_spinner_)), y cómo evitar cascadas de red (para que un hijo pueda obtener datos sin tener que esperar por cada padre). **Estos problemas aplican a cualquier biblioteca de UI, no solo a React. Resolverlos no es trivial, por eso los [frameworks](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos ofrecen mecanismos incorporados más eficientes de obtención de datos que obtener datos en Efectos.** From 8ad783f1eb050396af1d56eb95bf30e33698c983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:51:16 -0300 Subject: [PATCH 129/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index b80d2a5ad..2c254295f 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -786,7 +786,7 @@ function useData(url) { } ``` -Probablemente también querrás agregar alguna lógica para el manejo de errores y para seguir si el contenido está cargando. Puedes construir un Hook como este tú mismo o utilizar una de las muchas soluciones ya disponibles en el ecosistema de React. **Aunque esto por sí solo no será tan eficiente como usar el mecanismo de carga de datos integrado de un marco, trasladar la lógica de carga de datos a un Hook personalizado facilitará la adopción de una estrategia de carga de datos eficiente más tarde.** +Probablemente también querrás agregar lógica para el manejo de errores y para rastrear si el contenido está cargando. Puedes construir un Hook como este por ti mismo o utilizar una de las muchas soluciones ya disponibles en el ecosistema de React. **Aunque por sí solo esto no será tan eficiente como usar el mecanismo incorporado de obtención de datos de un framework, al mover la lógica de obtención de datos a un Hook personalizado, será más fácil adoptar una estrategia eficiente de obtención de datos más adelante.** En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes extraer una pieza de funcionalidad a un Hook personalizado con una API más declarativa y diseñada específicamente como el `useData` anterior. Cuantas menos llamadas innecesarias a `useEffect` tengas en tus componentes, más fácil será el mantenimiento de tu aplicación. From c3fa6a7a630cf5f86d446c1d267c916e1d403528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:51:30 -0300 Subject: [PATCH 130/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 2c254295f..e8f67a1a4 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -753,7 +753,7 @@ Manejar las condiciones de carrera no es la única dificultad al implementar la **Estos problemas aplican a cualquier biblioteca de UI, no solo a React. Resolverlos no es trivial, por eso los [frameworks](/learn/start-a-new-react-project#production-grade-react-frameworks) modernos ofrecen mecanismos incorporados más eficientes de obtención de datos que obtener datos en Efectos.** -Si no usas un framework (y no quieres construir el tuyo propio) pero te gustaría hacer que la carga de datos desde Efectos sea más ergonómica, considera extraer tu lógica de obtención a un Hook personalizado como en el siguiente ejemplo: +Si no utilizas un framework (y no quieres construir el tuyo propio) pero te gustaría hacer que la obtención de datos desde Efectos sea más cómoda, considera extraer tu lógica de obtención de datos en un Hook personalizado, como en este ejemplo: ```js {4} function SearchResults({ query }) { From 3ebef7d2a2e0c9819ea24a89777a1752e70f90c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Guillermo=20Hern=C3=A1ndez?= Date: Sun, 23 Jul 2023 14:51:39 -0300 Subject: [PATCH 131/131] Update src/content/learn/you-might-not-need-an-effect.md --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index e8f67a1a4..c7cc93fe0 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -788,7 +788,7 @@ function useData(url) { Probablemente también querrás agregar lógica para el manejo de errores y para rastrear si el contenido está cargando. Puedes construir un Hook como este por ti mismo o utilizar una de las muchas soluciones ya disponibles en el ecosistema de React. **Aunque por sí solo esto no será tan eficiente como usar el mecanismo incorporado de obtención de datos de un framework, al mover la lógica de obtención de datos a un Hook personalizado, será más fácil adoptar una estrategia eficiente de obtención de datos más adelante.** -En general, cada vez que debas recurrir a escribir Efectos, busca cuándo puedes extraer una pieza de funcionalidad a un Hook personalizado con una API más declarativa y diseñada específicamente como el `useData` anterior. Cuantas menos llamadas innecesarias a `useEffect` tengas en tus componentes, más fácil será el mantenimiento de tu aplicación. +En general, cada vez que te veas obligado a escribir Efectos, mantén un ojo para identificar cuándo puedes extraer una funcionalidad en un Hook personalizado con una API más declarativa y específica, como `useData` mencionado anteriormente. Cuantas menos llamadas directas a `useEffect` tengas en tus componentes, más fácil te resultará mantener tu aplicación.