diff --git a/src/content/reference/react/useEffect.md b/src/content/reference/react/useEffect.md index bc76bdfbe..89082f290 100644 --- a/src/content/reference/react/useEffect.md +++ b/src/content/reference/react/useEffect.md @@ -4,7 +4,7 @@ title: useEffect -`useEffect` is a React Hook that lets you [synchronize a component with an external system.](/learn/synchronizing-with-effects) +`useEffect` é um hook para React que permite que você [sincronize um componente com um sistema externo.](/learn/synchronizing-with-effects) ```js useEffect(setup, dependencies?) @@ -16,11 +16,11 @@ useEffect(setup, dependencies?) --- -## Reference {/*reference*/} +## Referência {/*reference*/} ### `useEffect(setup, dependencies?)` {/*useeffect*/} -Call `useEffect` at the top level of your component to declare an Effect: +Execute `useEffect` na raiz de seu componente para declarar um Effect: ```js import { useEffect } from 'react'; @@ -40,43 +40,43 @@ function ChatRoom({ roomId }) { } ``` -[See more examples below.](#usage) +[Veja mais exemplos abaixo.](#usage) -#### Parameters {/*parameters*/} +#### Parâmetros {/*parameters*/} -* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your component is first added to the DOM, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. After your component is removed from the DOM, React will run your cleanup function one last time. - -* **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If you omit this argument, your Effect will re-run after every re-render of the component. [See the difference between passing an array of dependencies, an empty array, and no dependencies at all.](#examples-dependencies) +* `setup`: A função que contém a lógica do seu Effect. A sua função de setup pode também opcionalmente retornar uma função de *cleanup*. Quando seu componente for adicionado ao DOM pela primeira vez, o React irá executar sua função de setup. Após cada rerenderização com mudança nas dependências, o React irá primeiro executar a função de cleanup (se você a definiu) com os valores antigos, e então executar sua função de setup com os valores novos. Após seu componente ser removido do DOM, o React executará sua função de cleanup uma última vez. -#### Returns {/*returns*/} +* **opcional** `dependencies`: A lista de todos valores reativos referenciados dentro do código de `setup`. Valores reativos incluem props, state e todas as variáveis e funções declaradas diretamente dentro do corpo do seu componente. Se seu linter estiver [configurado para React](/learn/editor-setup#linting), ele irá verificar que todos valores reativos estão corretamente especificados como dependência. A lista de dependências deve conter um número constante de itens e deve ser escrito inline como `[dep1, dep2, dep3]`. O React irá comparar cada dependência com seu valor anterior usando a comparação [`Object.is`](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/is). Se você emitir este argumento, seu Effect irá ser reexecutado a cada rerenderização do componente. [Veja a diferença entre passar um array de dependências, um array vazio, e não passar dependências.](#examples-dependencies) -`useEffect` returns `undefined`. +#### Retorno {/*returns*/} -#### Caveats {/*caveats*/} +`useEffect` retorna `undefined`. -* `useEffect` is a Hook, so you can only call it **at the top level of your component** or your own Hooks. You can't call it inside loops or conditions. If you need that, extract a new component and move the state into it. +#### Ressalvas {/*caveats*/} -* If you're **not trying to synchronize with some external system,** [you probably don't need an Effect.](/learn/you-might-not-need-an-effect) +* `useEffect` é um Hook, então você só pode o chamar **na raiz de seu componente** ou em seus próprios Hooks. Você não pode o chamar dentro de loops ou condições. Se você precisar fazer isto, extraia um novo componente e mova o state para dentro dele. -* When Strict Mode is on, React will **run one extra development-only setup+cleanup cycle** before the first real setup. This is a stress-test that ensures that your cleanup logic "mirrors" your setup logic and that it stops or undoes whatever the setup is doing. If this causes a problem, [implement the cleanup function.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) +* Se você **não está tentando sincronizar com algum sistema externo,** [você provavelmente não precisa de um Effect.](/learn/you-might-not-need-an-effect) -* If some of your dependencies are objects or functions defined inside the component, there is a risk that they will **cause the Effect to re-run more often than needed.** To fix this, remove unnecessary [object](#removing-unnecessary-object-dependencies) and [function](#removing-unnecessary-function-dependencies) dependencies. You can also [extract state updates](#updating-state-based-on-previous-state-from-an-effect) and [non-reactive logic](#reading-the-latest-props-and-state-from-an-effect) outside of your Effect. +* Quando o Strict Mode estiver ativo, o React irá **executar um ciclo extra de setup+cleanup somente em modo de desenvolvimento** antes o primeiro setup real. Isto é um teste que garante que sua lógica de cleanup "espelha" sua lógica de setup e que ela pára ou desfaz qualquer coisa que o setup esteja fazendo. Se isto causar um problema, [implemente a função de cleanup.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) -* If your Effect wasn't caused by an interaction (like a click), React will let the browser **paint the updated screen first before running your Effect.** If your Effect is doing something visual (for example, positioning a tooltip), and the delay is noticeable (for example, it flickers), replace `useEffect` with [`useLayoutEffect`.](/reference/react/useLayoutEffect) +* Se algumas de suas dependências forem objetos ou funções definidas dentro do componente, há um risco de que elas irão **fazer com que o Effect seja reexecutado com mais frequência do que o necessário.** Para consertar isto, remova [objetos](#removing-unnecessary-object-dependencies) e [funções](#removing-unnecessary-function-dependencies) desnecessários de suas dependências. Você também pode [extrair atualizações de state](#updating-state-based-on-previous-state-from-an-effect) e [lógica não-reativa](#reading-the-latest-props-and-state-from-an-effect) do seu Effect. -* Even if your Effect was caused by an interaction (like a click), **the browser may repaint the screen before processing the state updates inside your Effect.** Usually, that's what you want. However, if you must block the browser from repainting the screen, you need to replace `useEffect` with [`useLayoutEffect`.](/reference/react/useLayoutEffect) +* Se seu Effect não foi causado por uma interação (como um clique), o React deixará o navegador **pintar a tela atualizada antes de executar seu Effect.** Caso seu Effect esteja fazendo algo visual (por exemplo, posicionando um tooltip) e o atraso for perceptível (causando, por exemplo, tremulações), substitua `useEffect` por [`useLayoutEffect`.](/reference/react/useLayoutEffect) -* Effects **only run on the client.** They don't run during server rendering. +* Mesmo que seu Effect tenha sido causado por uma interação (como um clique), **o navegador pode repintar a tela antes de processar atualizações de state dentro de seu Effect.** Normalmente, é isto que você quer. No entanto, se você precisar impedir o navegador de repintar a tela, você precisará substituir `useEffect` por [`useLayoutEffect`.](/reference/react/useLayoutEffect) + +* Effects **executam somente no cliente.** Eles não são executados durante renderizações do lado do servidor. --- -## Usage {/*usage*/} +## Uso {/*usage*/} -### Connecting to an external system {/*connecting-to-an-external-system*/} +### Conectando a um sistema externo {/*connecting-to-an-external-system*/} -Some components need to stay connected to the network, some browser API, or a third-party library, while they are displayed on the page. These systems aren't controlled by React, so they are called *external.* +Alguns componentes precisam permanecer conectados à rede, APIs do navegador, ou bibliotecas de terceiros enquanto estão sendo exibidos na página. Estes sistemas não são controlados pelo React, então eles são chamados de *externos.* -To [connect your component to some external system,](/learn/synchronizing-with-effects) call `useEffect` at the top level of your component: +Para [conectar seu componente a algum sistema externo,](/learn/synchronizing-with-effects) chame `useEffect` na raiz de seu componente: ```js [[1, 8, "const connection = createConnection(serverUrl, roomId);"], [1, 9, "connection.connect();"], [2, 11, "connection.disconnect();"], [3, 13, "[serverUrl, roomId]"]] import { useEffect } from 'react'; @@ -96,45 +96,45 @@ function ChatRoom({ roomId }) { } ``` -You need to pass two arguments to `useEffect`: +Você precisa passar dois argumentos ao `useEffect`: -1. A *setup function* with setup code that connects to that system. - - It should return a *cleanup function* with cleanup code that disconnects from that system. -2. A list of dependencies including every value from your component used inside of those functions. +1. Uma *função de setup* com código de setup que conecta a este sistema. + - Ela deve retornar uma *função de cleanup* com código de cleanup que desconecta deste sistema. +2. Uma lista de dependências incluindo todos valores de seu componente utilizados dentro destas funções. -**React calls your setup and cleanup functions whenever it's necessary, which may happen multiple times:** +**O React executará suas funções de setup e cleanup quando necessário, o que pode ocorrer múltiplas vezes:** -1. Your setup code runs when your component is added to the page *(mounts)*. -2. After every re-render of your component where the dependencies have changed: - - First, your cleanup code runs with the old props and state. - - Then, your setup code runs with the new props and state. -3. Your cleanup code runs one final time after your component is removed from the page *(unmounts).* +1. Seu código de setup executa quando seu componente é adicionado à pagina *(mounts)*. +2. Após cada rerenderização do seu componente onde as dependências sofreram alterações: + - Primeiro, seu código de cleanup executa com os props e state antigos. + - Então, seu código de setup executa com os props e state novos. +3. Seu código de cleanup executa uma última vez depois que seu componente é removido da página *(unmounts).* -**Let's illustrate this sequence for the example above.** +**Vamos ilustrar esta sequência para o exemplo acima.** -When the `ChatRoom` component above gets added to the page, it will connect to the chat room with the initial `serverUrl` and `roomId`. If either `serverUrl` or `roomId` change as a result of a re-render (say, if the user picks a different chat room in a dropdown), your Effect will *disconnect from the previous room, and connect to the next one.* When the `ChatRoom` component is removed from the page, your Effect will disconnect one last time. +Quando o componente `ChatRoom` acima é adicionado à página, ele irá conectar com a sala de chat utilizando os valores iniciais de `serverUrl` e `roomId`. Se `serverUrl` ou `roomId` mudarem como resultado de uma rerenderização (causada, por exemplo, pelo usuário selecionando outra sala de chat numa lista), seu Effect irá *desconectar da sala anterior e conectar à próxima.* Quando o compoente `ChatRoom` for removido da página, seu Effect irá desconectar uma última vez. -**To [help you find bugs,](/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed) in development React runs setup and cleanup one extra time before the setup.** This is a stress-test that verifies your Effect's logic is implemented correctly. If this causes visible issues, your cleanup function is missing some logic. The cleanup function should stop or undo whatever the setup function was doing. The rule of thumb is that the user shouldn't be able to distinguish between the setup being called once (as in production) and a *setup* → *cleanup* → *setup* sequence (as in development). [See common solutions.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) +**No modo de desenvolvimento, para [ajudar você a encontrar erros,](/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed) o React executa setup e cleanup uma vez a mais antes de setup.** Isto é um teste que verifica se a lógica do seu Effect está implementada corretamente. Caso isto cause problemas, alguma lógica está faltando na sua função de cleanup. A função de cleanup deveria parar e desfazer qualquer coisa que a função de setup estava fazendo. De maneira geral, o usuário não deveria poder diferenciar se o setup está sendo chamado uma só vez (como em produção) ou numa sequência *setup* → *cleanup* → *setup* (como em desenvolvimento). [Veja soluções comuns.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) -**Try to [write every Effect as an independent process](/learn/lifecycle-of-reactive-effects#each-effect-represents-a-separate-synchronization-process) and [think about a single setup/cleanup cycle at a time.](/learn/lifecycle-of-reactive-effects#thinking-from-the-effects-perspective)** It shouldn't matter whether your component is mounting, updating, or unmounting. When your cleanup logic correctly "mirrors" the setup logic, your Effect is resilient to running setup and cleanup as often as needed. +**Tente [escrever cada Effect como um processo independente](/learn/lifecycle-of-reactive-effects#each-effect-represents-a-separate-synchronization-process) e [pense em um ciclo de setup/cleanup por vez.](/learn/lifecycle-of-reactive-effects#thinking-from-the-effects-perspective)** O fato de seu componente estar montando, atualizando ou desmontando não deveria importar. Quando sua lógica de cleanup "espelha" corretamente sua lógica de setup, seu Effect é resiliente o suficiente para rodar setup e cleanup o quanto for preciso. -An Effect lets you [keep your component synchronized](/learn/synchronizing-with-effects) with some external system (like a chat service). Here, *external system* means any piece of code that's not controlled by React, such as: +Um Effect permite que você [mantenha seu componente sincronizado](/learn/synchronizing-with-effects) com algum sistema externo (como um serviço de chat). Neste contexto, *sistema externo* significa qualquer trecho de código que não é controlado pelo React, como por exemplo: -* A timer managed with [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) and [`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval). -* An event subscription using [`window.addEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) and [`window.removeEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener). -* A third-party animation library with an API like `animation.start()` and `animation.reset()`. +* Um timer gerenciado usando [`setInterval()`](https://developer.mozilla.org/pt-BR/docs/Web/API/setInterval) e [`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval). +* Uma assinatura a eventos utilizando [`window.addEventListener()`](https://developer.mozilla.org/pt-BR/docs/Web/API/EventTarget/addEventListener) e [`window.removeEventListener()`](https://developer.mozilla.org/pt-BR/docs/Web/API/EventTarget/removeEventListener). +* Uma biblioteca de animações utilizando uma API como `animation.start()` e `animation.reset()`. -**If you're not connecting to any external system, [you probably don't need an Effect.](/learn/you-might-not-need-an-effect)** +**Se você não estiver conectando a um sistema externo, [você provavelmente não precisa de um Effect.](/learn/you-might-not-need-an-effect)** - + -#### Connecting to a chat server {/*connecting-to-a-chat-server*/} +#### Conectando a um servidor de chat {/*connecting-to-a-chat-server*/} -In this example, the `ChatRoom` component uses an Effect to stay connected to an external system defined in `chat.js`. Press "Open chat" to make the `ChatRoom` component appear. This sandbox runs in development mode, so there is an extra connect-and-disconnect cycle, as [explained here.](/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed) Try changing the `roomId` and `serverUrl` using the dropdown and the input, and see how the Effect re-connects to the chat. Press "Close chat" to see the Effect disconnect one last time. +Neste exemplo, o componente `ChatRoom` utiliza um Effect para permanecer conectado a um sistema externo definido em `chat.js`. Pressione "Abrir chat" para fazer com que o componente `ChatRoom` apareça. Este sandbox está executando em modo de desenvolvimento, portanto há um ciclo extra que conecta e desconecta, conforme [explicado aqui.](/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed) Experimente alterar `roomId` e `serverUrl` utilizando a lista de opções e o campo de texto, e perceba como o Effect reconecta ao chat. Pressione "Fechar chat" para ver o Effect disconectar uma última vez. @@ -156,35 +156,35 @@ function ChatRoom({ roomId }) { return ( <> -

Welcome to the {roomId} room!

+

Bem-vindo à sala {roomId}!

); } export default function App() { - const [roomId, setRoomId] = useState('general'); + const [roomId, setRoomId] = useState('geral'); const [show, setShow] = useState(false); return ( <> {show &&
} {show && } @@ -195,13 +195,13 @@ export default function App() { ```js chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // Uma implementação real se conectaria ao servidor return { connect() { - console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); + console.log('✅ Conectando-se ao canal "' + roomId + '" em ' + serverUrl + '...'); }, disconnect() { - console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); + console.log('❌ Desconectado do canal "' + roomId + '" em ' + serverUrl); } }; } @@ -216,9 +216,9 @@ button { margin-left: 10px; } -#### Listening to a global browser event {/*listening-to-a-global-browser-event*/} +#### Acompanhando um evento global do navegador {/*listening-to-a-global-browser-event*/} -In this example, the external system is the browser DOM itself. Normally, you'd specify event listeners with JSX, but you can't listen to the global [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) object this way. An Effect lets you connect to the `window` object and listen to its events. Listening to the `pointermove` event lets you track the cursor (or finger) position and update the red dot to move with it. +Neste exemplo, o sistema externo é o DOM do navegador em si. Normalmente, você especificaria event listeners com JSX, mas você não pode acompanhar o objeto global [`window`](https://developer.mozilla.org/pt-BR/docs/Web/API/Window) deste modo. Um Effect permite que você conecte ao objeto `window` e monitore seus eventos. Increver-se ao evento `pointermove` permite que você localize a posição do cursor (ou dedo) e atualize a posição do ponto vermelho. @@ -265,9 +265,9 @@ body { -#### Triggering an animation {/*triggering-an-animation*/} +#### Acionando uma animação {/*triggering-an-animation*/} -In this example, the external system is the animation library in `animation.js`. It provides a JavaScript class called `FadeInAnimation` that takes a DOM node as an argument and exposes `start()` and `stop()` methods to control the animation. This component [uses a ref](/learn/manipulating-the-dom-with-refs) to access the underlying DOM node. The Effect reads the DOM node from the ref and automatically starts the animation for that node when the component appears. +Neste exemplo, o sistema externo é a biblioteca de animação em `animation.js`. Ela provê uma classe JavaScript chamada `FadeInAnimation` que aceita um nó do DOM como argumento e expõe os métodos `start()` e `stop()` para controlar a animação. Este componente [utiliza um ref](/learn/manipulating-the-dom-with-refs) para acessar o nó do DOM subjacente. O Effect lê o nó do DOM a partir do ref e automaticamente inicia a animação para aquele nó quando o componente aparece. @@ -298,7 +298,7 @@ function Welcome() { backgroundImage: 'radial-gradient(circle, rgba(63,94,251,1) 0%, rgba(252,70,107,1) 100%)' }} > - Welcome + Bem-vindo ); } @@ -308,7 +308,7 @@ export default function App() { return ( <>
{show && } @@ -325,11 +325,11 @@ export class FadeInAnimation { start(duration) { this.duration = duration; if (this.duration === 0) { - // Jump to end immediately + // Pular imediatamente ao fim this.onProgress(1); } else { this.onProgress(0); - // Start animating + // Iniciar animação this.startTime = performance.now(); this.frameId = requestAnimationFrame(() => this.onFrame()); } @@ -339,7 +339,7 @@ export class FadeInAnimation { const progress = Math.min(timePassed / this.duration, 1); this.onProgress(progress); if (progress < 1) { - // We still have more frames to paint + // Teremos mais quadros para pintar this.frameId = requestAnimationFrame(() => this.onFrame()); } } @@ -364,9 +364,9 @@ html, body { min-height: 300px; } -#### Controlling a modal dialog {/*controlling-a-modal-dialog*/} +#### Controlando uma caixa de diálogo {/*controlling-a-modal-dialog*/} -In this example, the external system is the browser DOM. The `ModalDialog` component renders a [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog) element. It uses an Effect to synchronize the `isOpen` prop to the [`showModal()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal) and [`close()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close) method calls. +Neste exemplo, o sistema externo é o DOM do navegador. O componente `ModalDialog` renderiza um elemento [``](https://developer.mozilla.org/pt-BR/docs/Web/HTML/Element/dialog). Ele utiliza um Effect para sincronizar a prop `isOpen` com as chamadas de método [`showModal()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal) e [`close()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close). @@ -379,14 +379,14 @@ export default function App() { return ( <> - Hello there! + Olá!
+ }}>Fechar
); @@ -424,9 +424,9 @@ body { -#### Tracking element visibility {/*tracking-element-visibility*/} +#### Monitorando visibilidade de elementos {/*tracking-element-visibility*/} -In this example, the external system is again the browser DOM. The `App` component displays a long list, then a `Box` component, and then another long list. Scroll the list down. Notice that when the `Box` component appears in the viewport, the background color changes to black. To implement this, the `Box` component uses an Effect to manage an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). This browser API notifies you when the DOM element is visible in the viewport. +Neste exemplo, o sistema externo é novamente o DOM do navegador. O componente `App` exibe uma lista longa, o componente `Box`, e então outra lista longa. Role a lista pra baixo. Perceba que quando o componente `Box` aparece na viewport, a cor de fundo muda para preto. Para implementar isto, o componente `Box` usa um Effect para gerenciar um [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). Esta API do navegador lhe notifica quando o elemento DOM está visível na viewport. @@ -448,7 +448,7 @@ export default function App() { function LongSection() { const items = []; for (let i = 0; i < 50; i++) { - items.push(
  • Item #{i} (keep scrolling)
  • ); + items.push(
  • Item #{i} (continue rolando)
  • ); } return
      {items}
    } @@ -500,11 +500,11 @@ export default function Box() { --- -### Wrapping Effects in custom Hooks {/*wrapping-effects-in-custom-hooks*/} +### Encapsulando Effects em Hooks customizados {/*wrapping-effects-in-custom-hooks*/} -Effects are an ["escape hatch":](/learn/escape-hatches) you use them when you need to "step outside React" and when there is no better built-in solution for your use case. If you find yourself often needing to manually write Effects, it's usually a sign that you need to extract some [custom Hooks](/learn/reusing-logic-with-custom-hooks) for common behaviors your components rely on. +Effects são uma ["válvula de escape":](/learn/escape-hatches) você as usa quando precisa "sair do React" e quando nao há uma solução integrada melhor para seu caso de uso. Se você perceber que tem precisado escrever muitos Effects, isso é geralmente um sinal que você precisa extrair alguns [Hooks customizados](/learn/reusing-logic-with-custom-hooks) para comportamentos comuns que seus componentes dependem. -For example, this `useChatRoom` custom Hook "hides" the logic of your Effect behind a more declarative API: +Por exemplo, este Hook customizado `useChatRoom` "esconde" a lógica do seu Effect atrás de uma API mais declarativa: ```js {1,11} function useChatRoom({ serverUrl, roomId }) { @@ -520,7 +520,7 @@ function useChatRoom({ serverUrl, roomId }) { } ``` -Then you can use it from any component like this: +Então você pode utilizá-lo em qualquer componente deste modo: ```js {4-7} function ChatRoom({ roomId }) { @@ -531,17 +531,17 @@ function ChatRoom({ roomId }) { serverUrl: serverUrl }); // ... -```` +``` -There are also many excellent custom Hooks for every purpose available in the React ecosystem. +Existem também muitos Hooks customizados excelentes para qualquer propósito disponíveis no ecossistema do React. -[Learn more about wrapping Effects in custom Hooks.](/learn/reusing-logic-with-custom-hooks) +[Aprenda mais sobre encapsular Effects em Hooks customizados.](/learn/reusing-logic-with-custom-hooks) - + -#### Custom `useChatRoom` Hook {/*custom-usechatroom-hook*/} +#### Hook customizado `useChatRoom` {/*custom-usechatroom-hook*/} -This example is identical to one of the [earlier examples,](#examples-connecting) but the logic is extracted to a custom Hook. +Este exemplo é idêntico a um dos [exemplos anteriores,](#examples-connecting), com a lógica extraída para um Hook customizado. @@ -560,35 +560,35 @@ function ChatRoom({ roomId }) { return ( <> -

    Welcome to the {roomId} room!

    +

    Bem-vindo à sala {roomId}!

    ); } export default function App() { - const [roomId, setRoomId] = useState('general'); + const [roomId, setRoomId] = useState('geral'); const [show, setShow] = useState(false); return ( <> {show &&
    } {show && } @@ -614,13 +614,13 @@ export function useChatRoom({ serverUrl, roomId }) { ```js chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // Uma implementação real se conectaria ao servidor return { connect() { - console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); + console.log('✅ Conectando-se ao canal "' + roomId + '" em ' + serverUrl + '...'); }, disconnect() { - console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); + console.log('❌ Desconectado do canal "' + roomId + '" em ' + serverUrl); } }; } @@ -635,9 +635,9 @@ button { margin-left: 10px; } -#### Custom `useWindowListener` Hook {/*custom-usewindowlistener-hook*/} +#### Hook customizado `useWindowListener` {/*custom-usewindowlistener-hook*/} -This example is identical to one of the [earlier examples,](#examples-connecting) but the logic is extracted to a custom Hook. +Este exemplo é idêntico a um dos [exemplos anteriores,](#examples-connecting), com a lógica extraída para um Hook customizado. @@ -692,9 +692,9 @@ body { -#### Custom `useIntersectionObserver` Hook {/*custom-useintersectionobserver-hook*/} +#### Hook customizado `useIntersectionObserver` {/*custom-useintersectionobserver-hook*/} -This example is identical to one of the [earlier examples,](#examples-connecting) but the logic is partially extracted to a custom Hook. +Este exemplo é idêntico a um dos [exemplos anteriores,](#examples-connecting), com a lógica extraída para um Hook customizado. @@ -716,7 +716,7 @@ export default function App() { function LongSection() { const items = []; for (let i = 0; i < 50; i++) { - items.push(
  • Item #{i} (keep scrolling)
  • ); + items.push(
  • Item #{i} (continue rolando)
  • ); } return
      {items}
    } @@ -784,11 +784,11 @@ export function useIntersectionObserver(ref) { --- -### Controlling a non-React widget {/*controlling-a-non-react-widget*/} +### Controlando um widget não React {/*controlling-a-non-react-widget*/} -Sometimes, you want to keep an external system synchronized to some prop or state of your component. +Algumas vezes, você precisa manter um sistema externo sincronizado com alguma prop ou state do seu componente. -For example, if you have a third-party map widget or a video player component written without React, you can use an Effect to call methods on it that make its state match the current state of your React component. This Effect creates an instance of a `MapWidget` class defined in `map-widget.js`. When you change the `zoomLevel` prop of the `Map` component, the Effect calls the `setZoom()` on the class instance to keep it synchronized: +Por exemplo, se você possui um widget de mapa ou um componente de reprodução de vídeo não escritos em React, você pode utilizar um Effect para executar métodos nele, fazendo com que seu estado corresponda ao estado atual do seu componente React. Este Effect cria uma instância de uma classe `MapWidget` definida em `map-widget.js`. Quando você altera a prop `zoomLevel` do componente `Map`, o Effect chama o método `setZoom()` da instância da classe para manter o valor sincronizado: @@ -818,7 +818,7 @@ export default function App() { const [zoomLevel, setZoomLevel] = useState(0); return ( <> - Zoom level: {zoomLevel}x + Nível de zoom: {zoomLevel}x
    @@ -888,15 +888,15 @@ button { margin: 5px; }
    -In this example, a cleanup function is not needed because the `MapWidget` class manages only the DOM node that was passed to it. After the `Map` React component is removed from the tree, both the DOM node and the `MapWidget` class instance will be automatically garbage-collected by the browser JavaScript engine. +Neste exemplo, uma função de cleanup não é necessária, porque a classe `MapWidget` controla somente o nó DOM que foi passado para ela. Após a remoção do componente React `Map`, tanto o nó DOM quanto a instância da classe `MapWidget` serão automaticamente coletados pela engine JavaScript do navegador. --- -### Fetching data with Effects {/*fetching-data-with-effects*/} +### Buscando dados com Effects {/*fetching-data-with-effects*/} -You can use an Effect to fetch data for your component. Note that [if you use a framework,](/learn/start-a-new-react-project#production-grade-react-frameworks) using your framework's data fetching mechanism will be a lot more efficient than writing Effects manually. +Você pode usar um Effect para buscar dados para seu componente. Note que [se você usa um framework,](/learn/start-a-new-react-project#production-grade-react-frameworks) utilizar o mecanismo de busca de dados do seu framework será muito mais eficiente do que escrever Effects manualmente. -If you want to fetch data from an Effect manually, your code might look like this: +Se você quiser buscar dados com um Effect manualmente, precisará de um código parecido com este: ```js import { useState, useEffect } from 'react'; @@ -922,7 +922,7 @@ export default function Page() { // ... ``` -Note the `ignore` variable which is initialized to `false`, and is set to `true` during cleanup. This ensures [your code doesn't suffer from "race conditions":](https://maxrozen.com/race-conditions-fetching-data-react-with-useeffect) network responses may arrive in a different order than you sent them. +Perceba a variável `ignore`, que é inicializada como `false` e então atualizada para `true` durante o cleanup. Isso garante que [seu código não sofra com "race conditions":](https://maxrozen.com/race-conditions-fetching-data-react-with-useeffect) respostas da rede podem chegar numa ordem diferente da que você as enviou. @@ -956,7 +956,7 @@ export default function Page() {
    -

    {bio ?? 'Loading...'}

    +

    {bio ?? 'Carregando...'}

    ); } @@ -967,7 +967,7 @@ export async function fetchBio(person) { const delay = person === 'Bob' ? 2000 : 200; return new Promise(resolve => { setTimeout(() => { - resolve('This is ' + person + '’s bio.'); + resolve('Esta é a página de ' + person + '.'); }, delay); }) } @@ -975,7 +975,8 @@ export async function fetchBio(person) {
    -You can also rewrite using the [`async` / `await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) syntax, but you still need to provide a cleanup function: + +Você também pode reescrever utilizando a sintaxe [`async` / `await`](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/async_function), mas ainda precisará definir a função de cleanup: @@ -1012,7 +1013,7 @@ export default function Page() {
    -

    {bio ?? 'Loading...'}

    +

    {bio ?? 'Carregando...'}

    ); } @@ -1023,7 +1024,7 @@ export async function fetchBio(person) { const delay = person === 'Bob' ? 2000 : 200; return new Promise(resolve => { setTimeout(() => { - resolve('This is ' + person + '’s bio.'); + resolve('Esta é a página de ' + person + '.'); }, delay); }) } @@ -1031,50 +1032,50 @@ export async function fetchBio(person) {
    -Writing data fetching directly in Effects gets repetitive and makes it difficult to add optimizations like caching and server rendering later. [It's easier to use a custom Hook--either your own or maintained by the community.](/learn/reusing-logic-with-custom-hooks#when-to-use-custom-hooks) +Implementar busca de dados diretamente com Effects se torna repetitivo e dificulta a posterior adição de otimizações como caching e renderização do lado do servidor. [É mais fácil utilizar um Hook customizado -- ou por você ou mantido pela comunidade.](/learn/reusing-logic-with-custom-hooks#when-to-use-custom-hooks) -#### What are good alternatives to data fetching in Effects? {/*what-are-good-alternatives-to-data-fetching-in-effects*/} +#### Quais as melhores alternativas à busca de dados em Effects? {/*what-are-good-alternatives-to-data-fetching-in-effects*/} -Writing `fetch` calls inside Effects is a [popular way to fetch data](https://www.robinwieruch.de/react-hooks-fetch-data/), especially in fully client-side apps. This is, however, a very manual approach and it has significant downsides: +Escrever chamadas `fetch` dentro de Effects é um [jeito pupular de buscar dados](https://www.robinwieruch.de/react-hooks-fetch-data/), especialmente em aplicações totalmente client-side. Esta é, entretanto, uma abordagem muito manual e possui desvantagens significativas: -- **Effects don't run on the server.** This means that the initial server-rendered HTML will only include a loading state with no data. The client computer will have to download all JavaScript and render your app only to discover that now it needs to load the data. This is not very efficient. -- **Fetching directly in Effects makes it easy to create "network waterfalls".** You render the parent component, it fetches some data, renders the child components, and then they start fetching their data. If the network is not very fast, this is significantly slower than fetching all data in parallel. -- **Fetching directly in Effects usually means you don't preload or cache data.** For example, if the component unmounts and then mounts again, it would have to fetch the data again. -- **It's not very ergonomic.** There's quite a bit of boilerplate code involved when writing `fetch` calls in a way that doesn't suffer from bugs like [race conditions.](https://maxrozen.com/race-conditions-fetching-data-react-with-useeffect) +- **Effects não executam no servidor.** Isto significa que o HTML inicial renderizado pelo servidor irá conter somente o estado de "carregando", sem os dados. O computador do cliente terá que fazer o download de todo o JavaScript e renderizar sua aplicação para somente então descobrir que precisará buscar mais dados. Isto não é muito eficiente. +- **Buscar dados diretamente dentro de Effects facilita a criação de "network waterfalls".** Você renderiza o componente pai, ele busca alguns dados, renderiza os componentes filho, e então eles começam a buscar seus próprios dados. Se a rede não for muito rápida, isto é significativamente mais devagar do que buscar todos os dados em paralelo. +- **Buscar dados diretamente dentro de Effects normalmente significa que você não pré-carrega nem armazena dados em cache.** Por exemplo, se o componente desmontar e então montar de novo, ele teria que buscar os dados novamente. +- **Não é muito ergonômico.** Existe muito código de boilerplate envolvido quando escrevemos chamadas `fetch` evitando problemas como [race conditions.](https://maxrozen.com/race-conditions-fetching-data-react-with-useeffect) -This list of downsides is not specific to React. It applies to fetching data on mount with any library. Like with routing, data fetching is not trivial to do well, so we recommend the following approaches: +Esta lista de desvantagens não é específica ao React. Ela se aplica à busca de dados ao montar componentes em qualquer biblioteca. Assim como roteamento, busca de dados não é um problema trivial de resolver, portanto recomendamos as seguintes abordagens: -- **If you use a [framework](/learn/start-a-new-react-project#production-grade-react-frameworks), use its built-in data fetching mechanism.** Modern React frameworks have integrated data fetching mechanisms that are efficient and don't suffer from the above pitfalls. -- **Otherwise, consider using or building a client-side cache.** Popular open source solutions include [React Query](https://react-query.tanstack.com/), [useSWR](https://swr.vercel.app/), and [React Router 6.4+.](https://beta.reactrouter.com/en/main/start/overview) You can build your own solution too, in which case you would use Effects under the hood but also add logic for deduplicating requests, caching responses, and avoiding network waterfalls (by preloading data or hoisting data requirements to routes). +- **Se você usa um [framework](/learn/start-a-new-react-project#production-grade-react-frameworks), utilize os mecanismos de busca de dados integrados a ele.** Frameworks React modernos já possuem mecanismos para busca de dados que são eficientes e não sofrem com as desvantagens mencionadas anteriormente. +- **Caso contrário, considere utilizar ou construir um sistema de cache de dados no lado do cliente.** Soluções populares de código aberto incluem [React Query](https://react-query.tanstack.com/), [useSWR](https://swr.vercel.app/) e [React Router 6.4+.](https://beta.reactrouter.com/en/main/start/overview) Você pode construir sua própria solução também, neste caso você utilizaria Effects por debaixo dos panos, mas também adicionaria lógicas para deduplicar chamadas, realizar cache das respostas e evitar network waterfalls (pré-carregando dados ou elevando requisitos de dados para as rotas). -You can continue fetching data directly in Effects if neither of these approaches suit you. +Você pode continuar buscando dados diretamente em Effects se nenhuma destas abordagens lhe servir. --- -### Specifying reactive dependencies {/*specifying-reactive-dependencies*/} +### Especificando dependências reativas {/*specifying-reactive-dependencies*/} -**Notice that you can't "choose" the dependencies of your Effect.** Every reactive value used by your Effect's code must be declared as a dependency. Your Effect's dependency list is determined by the surrounding code: +**Note que você não pode "escolher" as dependências do seu Effect.** Cada valor reativo usado pelo código de seu Effect deve ser declarado como uma dependência. A lista de dependências do seu Effect é determinada pelo código ao seu redor: ```js [[2, 1, "roomId"], [2, 2, "serverUrl"], [2, 5, "serverUrl"], [2, 5, "roomId"], [2, 8, "serverUrl"], [2, 8, "roomId"]] -function ChatRoom({ roomId }) { // This is a reactive value - const [serverUrl, setServerUrl] = useState('https://localhost:1234'); // This is a reactive value too +function ChatRoom({ roomId }) { // Este é um valor reativo + const [serverUrl, setServerUrl] = useState('https://localhost:1234'); // Este é outro valor reativo useEffect(() => { - const connection = createConnection(serverUrl, roomId); // This Effect reads these reactive values + const connection = createConnection(serverUrl, roomId); // Este Effect lê tais valores reativos connection.connect(); return () => connection.disconnect(); - }, [serverUrl, roomId]); // ✅ So you must specify them as dependencies of your Effect + }, [serverUrl, roomId]); // ✅ Portanto você deve especificá-los como dependências de seu Effect // ... } ``` -If either `serverUrl` or `roomId` change, your Effect will reconnect to the chat using the new values. +Se `serverUrl` ou `roomId` forem alterados, seu Effect irá reconectar ao chat utilizando os novos valores. -**[Reactive values](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) include props and all variables and functions declared directly inside of your component.** Since `roomId` and `serverUrl` are reactive values, you can't remove them from the dependencies. If you try to omit them and [your linter is correctly configured for React,](/learn/editor-setup#linting) the linter will flag this as a mistake you need to fix: +**[Valores reativos](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) incluem props e todas as variáveis e funções declaradas diretamente dentro de seu componente.** Dado que `roomId` e `serverUrl` são valores reativos, você não os pode remover das dependências. Se você tentar omiti-los e [seu linter estiver corretamente configurado para React,](/learn/editor-setup#linting) o linter irá marcar isto como um erro que precisa ser corrigido: ```js {8} function ChatRoom({ roomId }) { @@ -1089,68 +1090,68 @@ function ChatRoom({ roomId }) { } ``` -**To remove a dependency, you need to ["prove" to the linter *doesn't need* to be a dependency.](/learn/removing-effect-dependencies#removing-unnecessary-dependencies)** For example, you can move `serverUrl` out of your component to prove that it's not reactive and won't change on re-renders: +**Para remover uma dependência, você precisa ["provar" ao linter que ela *não precisa* ser uma dependência.](/learn/removing-effect-dependencies#removing-unnecessary-dependencies)** Por exemplo, você pode mover `serverUrl` para fora de seu componente para provar que o valor não é reativo e não irá ser alterado em rerenderizações: ```js {1,8} -const serverUrl = 'https://localhost:1234'; // Not a reactive value anymore +const serverUrl = 'https://localhost:1234'; // Não mais um valor reativo function ChatRoom({ roomId }) { useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => connection.disconnect(); - }, [roomId]); // ✅ All dependencies declared + }, [roomId]); // ✅ Todas dependências declaradas // ... } ``` -Now that `serverUrl` is not a reactive value (and can't change on a re-render), it doesn't need to be a dependency. **If your Effect's code doesn't use any reactive values, its dependency list should be empty (`[]`):** +Agora que `serverUrl` não é mais um valor reativo (e não pode ser alterado em uma rerenderização), ele não precisa mais ser uma dependência. **Se o código do seu Effect não utilizar nenhum valor reativo, a lista de dependências deveria ser vazia (`[]`):** ```js {1,2,9} -const serverUrl = 'https://localhost:1234'; // Not a reactive value anymore -const roomId = 'music'; // Not a reactive value anymore +const serverUrl = 'https://localhost:1234'; // Não mais um valor reativo +const roomId = 'music'; // Não mais um valor reativo function ChatRoom() { useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => connection.disconnect(); - }, []); // ✅ All dependencies declared + }, []); // ✅ Todas dependências declaradas // ... } ``` -[An Effect with empty dependencies](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means) doesn't re-run when any of your component's props or state change. +[Um Effect com dependências vazias](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means) não é reexecutado mesmo quando as props ou state de qualquer de seus componentes for atualizado. -If you have an existing codebase, you might have some Effects that suppress the linter like this: +Se você tiver um codebase existente, você pode ter alguns Effects que suprimem o linter deste modo: ```js {3-4} useEffect(() => { // ... - // 🔴 Avoid suppressing the linter like this: + // 🔴 Evite suprimir o linter deste modo: // eslint-ignore-next-line react-hooks/exhaustive-deps }, []); ``` -**When dependencies don't match the code, there is a high risk of introducing bugs.** By suppressing the linter, you "lie" to React about the values your Effect depends on. [Instead, prove they're unnecessary.](/learn/removing-effect-dependencies#removing-unnecessary-dependencies) +**Quando as dependências não correspondem ao código, existe um alto risco de introduzir erros.** Ao suprimir o linter, você "mente" ao React sobre os valores nos quais o seu Effect depende. [Ao invés disto, prove que eles são desnecessários.](/learn/removing-effect-dependencies#removing-unnecessary-dependencies) - + -#### Passing a dependency array {/*passing-a-dependency-array*/} +#### Passando uma lista de dependências {/*passing-a-dependency-array*/} -If you specify the dependencies, your Effect runs **after the initial render _and_ after re-renders with changed dependencies.** +Se você especificar as dependências, seu Effect executa **após a renderização inicial _e_ depois que rerenderizar com dependências atualizadas.** ```js {3} useEffect(() => { // ... -}, [a, b]); // Runs again if a or b are different +}, [a, b]); // Executa novamente caso a ou b sejam alterados ``` -In the below example, `serverUrl` and `roomId` are [reactive values,](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) so they both must be specified as dependencies. As a result, selecting a different room in the dropdown or editing the server URL input causes the chat to re-connect. However, since `message` isn't used in the Effect (and so it isn't a dependency), editing the message doesn't re-connect to the chat. +No exemplo abaixo, `serverUrl` e `roomId` são [valores reativos,](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) então eles devem ambos serem especificados como dependências. Como resultado, selecionar um canal diferente na lista ou editar a URL do servidor causará uma reconexão no chat. No entanto, como `message` não é utilizado no Effect (e então não é uma dependência), editar a mensagem não causará reconexão. @@ -1173,15 +1174,15 @@ function ChatRoom({ roomId }) { return ( <> -

    Welcome to the {roomId} room!

    +

    Bem-vindo à sala {roomId}!

    @@ -1190,21 +1191,21 @@ function ChatRoom({ roomId }) { export default function App() { const [show, setShow] = useState(false); - const [roomId, setRoomId] = useState('general'); + const [roomId, setRoomId] = useState('geral'); return ( <> {show &&
    } @@ -1216,13 +1217,13 @@ export default function App() { ```js chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // Uma implementação real se conectaria ao servidor return { connect() { - console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); + console.log('✅ Conectando-se ao canal "' + roomId + '" em ' + serverUrl + '...'); }, disconnect() { - console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); + console.log('❌ Desconectado do canal "' + roomId + '" em ' + serverUrl); } }; } @@ -1237,20 +1238,19 @@ button { margin-left: 5px; } -#### Passing an empty dependency array {/*passing-an-empty-dependency-array*/} +#### Passando uma lista de dependências vazia {/*passing-an-empty-dependency-array*/} -If your Effect truly doesn't use any reactive values, it will only run **after the initial render.** +Se seu Effect realmente não utilizar nenhum valor reativo, ele irá executar somente **após a renderização inicial.** ```js {3} useEffect(() => { // ... -}, []); // Does not run again (except once in development) +}, []); // Não executa novamente (exceto por uma vez em desenvolvimento) ``` -**Even with empty dependencies, setup and cleanup will [run one extra time in development](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) to help you find bugs.** - +**Mesmo com dependências vazias, as funções de setup e cleanup irão [executar uma vez a mais em desenvolvimento](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) para ajudá-lo a encontrar erros.** -In this example, both `serverUrl` and `roomId` are hardcoded. Since they're declared outside the component, they are not reactive values, and so they aren't dependencies. The dependency list is empty, so the Effect doesn't re-run on re-renders. +Neste exemplo, tanto `serverUrl` quanto `roomId` estão hardcoded. Já que eles são declarados fora do componente, eles não são valores reativos, e portanto não são dependências. A lista de dependências está vazia, então o Effect não é reexecutado em rerenderizações. @@ -1259,7 +1259,7 @@ import { useState, useEffect } from 'react'; import { createConnection } from './chat.js'; const serverUrl = 'https://localhost:1234'; -const roomId = 'music'; +const roomId = 'música'; function ChatRoom() { const [message, setMessage] = useState(''); @@ -1272,9 +1272,9 @@ function ChatRoom() { return ( <> -

    Welcome to the {roomId} room!

    +

    Bem-vindo à sala {roomId}!

    @@ -1286,7 +1286,7 @@ export default function App() { return ( <> {show &&
    } {show && } @@ -1297,13 +1297,13 @@ export default function App() { ```js chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // Uma implementação real se conectaria ao servidor return { connect() { - console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); + console.log('✅ Conectando-se ao canal "' + roomId + '" em ' + serverUrl + '...'); }, disconnect() { - console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); + console.log('❌ Desconectado do canal "' + roomId + '" em ' + serverUrl); } }; } @@ -1314,17 +1314,17 @@ export function createConnection(serverUrl, roomId) { -#### Passing no dependency array at all {/*passing-no-dependency-array-at-all*/} +#### Não passando nenhuma lista de dependências {/*passing-no-dependency-array-at-all*/} -If you pass no dependency array at all, your Effect runs **after every single render (and re-render)** of your component. +Se você não passar nenhuma lista de dependências, seu Effect executa **após toda renderização (e rerenderização)** do seu componente. ```js {3} useEffect(() => { // ... -}); // Always runs again +}); // É sempre executado novamente ``` -In this example, the Effect re-runs when you change `serverUrl` and `roomId`, which is sensible. However, it *also* re-runs when you change the `message`, which is probably undesirable. This is why usually you'll specify the dependency array. +Neste exemplo, o Effect é reexecutado quando você altera `serverUrl` e `roomId`, o que é razoável. No entento, ele *também* é reexecutado quando `message` é alterado, o que provavelmente é indesejado. É por isso que normalmente você especificará a lista de dependências. @@ -1347,15 +1347,15 @@ function ChatRoom({ roomId }) { return ( <> -

    Welcome to the {roomId} room!

    +

    Bem-vindo à sala {roomId}!

    @@ -1364,21 +1364,21 @@ function ChatRoom({ roomId }) { export default function App() { const [show, setShow] = useState(false); - const [roomId, setRoomId] = useState('general'); + const [roomId, setRoomId] = useState('geral'); return ( <> {show &&
    } @@ -1390,13 +1390,13 @@ export default function App() { ```js chat.js export function createConnection(serverUrl, roomId) { - // A real implementation would actually connect to the server + // Uma implementação real se conectaria ao servidor return { connect() { - console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); + console.log('✅ Conectando-se ao canal "' + roomId + '" em ' + serverUrl + '...'); }, disconnect() { - console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); + console.log('❌ Desconectado do canal "' + roomId + '" em ' + serverUrl); } }; } @@ -1415,9 +1415,9 @@ button { margin-left: 5px; } --- -### Updating state based on previous state from an Effect {/*updating-state-based-on-previous-state-from-an-effect*/} +### Atualizando state baseado em valores anteriores num Effect {/*updating-state-based-on-previous-state-from-an-effect*/} -When you want to update state based on previous state from an Effect, you might run into a problem: +Quando você precisar atualizar o state baseado em um valor anterior do state dentro de um Effect, você pode ter o seguinte problema: ```js {6,9} function Counter() { @@ -1425,17 +1425,17 @@ function Counter() { useEffect(() => { const intervalId = setInterval(() => { - setCount(count + 1); // You want to increment the counter every second... + setCount(count + 1); // Você quer incrementar o contador a cada segundo... }, 1000) return () => clearInterval(intervalId); - }, [count]); // 🚩 ... but specifying `count` as a dependency always resets the interval. + }, [count]); // 🚩 ... mas especificar `count` como uma dependência sempre reseta o intervalo. // ... } ``` -Since `count` is a reactive value, it must be specified in the list of dependencies. However, that causes the Effect to cleanup and setup again every time the `count` changes. This is not ideal. +Dado que `count` é um valor reativo, ele deve ser especificado na lista de dependências. No entanto, isto faz com que o Effect rode as funções de cleanup e setup novamente a cada vez que `count` muda. Isto não é ideal. -To fix this, [pass the `c => c + 1` state updater](/reference/react/useState#updating-state-based-on-the-previous-state) to `setCount`: +Para arrumar isto, [passe o state updater `c => c + 1`](/reference/react/useState#updating-state-based-on-the-previous-state) a `setCount`: @@ -1447,10 +1447,10 @@ export default function Counter() { useEffect(() => { const intervalId = setInterval(() => { - setCount(c => c + 1); // ✅ Pass a state updater + setCount(c => c + 1); // ✅ Passe um state updater }, 1000); return () => clearInterval(intervalId); - }, []); // ✅ Now count is not a dependency + }, []); // ✅ Agora count não é uma dependência return

    {count}

    ; } @@ -1470,14 +1470,15 @@ body {
    -Now that you're passing `c => c + 1` instead of `count + 1`, [your Effect no longer needs to depend on `count`.](/learn/removing-effect-dependencies#are-you-reading-some-state-to-calculate-the-next-state) As a result of this fix, it won't need to cleanup and setup the interval again every time the `count` changes. + +Agora que você está passando `c => c + 1` ao invés de `count + 1`, [seu Effect não precisa mais depender de `count`.](/learn/removing-effect-dependencies#are-you-reading-some-state-to-calculate-the-next-state) Como resultado desta correção, o intervalo não precisará mais ser limpo e setado toda vez que `count` atualizar. --- -### Removing unnecessary object dependencies {/*removing-unnecessary-object-dependencies*/} +### Removendo objetos desnecessários das dependências {/*removing-unnecessary-object-dependencies*/} -If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every render because the `options` object is [different for every render:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally) +Se seu Effect depende de um objeto ou uma função criada durante a renderização, ele pode executar com muita frequência. Por exemplo, este Effect reconecta após cada renderização, pois o objeto `options` é [diferente para cada renderização:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally) ```js {6-9,12,15} const serverUrl = 'https://localhost:1234'; @@ -1485,20 +1486,20 @@ const serverUrl = 'https://localhost:1234'; function ChatRoom({ roomId }) { const [message, setMessage] = useState(''); - const options = { // 🚩 This object is created from scratch on every re-render + const options = { // 🚩 Este objeto é recriado a cada rerenderização serverUrl: serverUrl, roomId: roomId }; useEffect(() => { - const connection = createConnection(options); // It's used inside the Effect + const connection = createConnection(options); // E usado dentro do Effect connection.connect(); return () => connection.disconnect(); - }, [options]); // 🚩 As a result, these dependencies are always different on a re-render + }, [options]); // 🚩 Como resultado, estas dependências são sempre diferentes numa rerenderização // ... ``` -Avoid using an object created during rendering as a dependency. Instead, create the object inside the Effect: +Evite utilizar objetos criados durante a renderização como dependência. Ao invés disto, crie estes objetos dentro do Effect: @@ -1523,25 +1524,25 @@ function ChatRoom({ roomId }) { return ( <> -

    Welcome to the {roomId} room!

    +

    Bem-vindo à sala {roomId}!

    setMessage(e.target.value)} /> ); } export default function App() { - const [roomId, setRoomId] = useState('general'); + const [roomId, setRoomId] = useState('geral'); return ( <>
    @@ -1553,13 +1554,13 @@ export default function App() { ```js chat.js export function createConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // Uma implementação real se conectaria ao servidor return { connect() { - console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); + console.log('✅ Conectando-se ao canal "' + roomId + '" em ' + serverUrl + '...'); }, disconnect() { - console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); + console.log('❌ Desconectado do canal "' + roomId + '" em ' + serverUrl); } }; } @@ -1572,21 +1573,21 @@ button { margin-left: 10px; }
    -Now that you create the `options` object inside the Effect, the Effect itself only depends on the `roomId` string. +Agora que você criou o objeto `options` dentro do Effect, o Effect em si depende somente da string `roomId`. -With this fix, typing into the input doesn't reconnect the chat. Unlike an object which gets re-created, a string like `roomId` doesn't change unless you set it to another value. [Read more about removing dependencies.](/learn/removing-effect-dependencies) +Com esta correção, escrever no campo de texto não causa reconexão ao chat. Diferentemente de um objeto que é recriado, uma string como `roomId` não é modificada a não ser que você altere seu valor. [Leia mais sobre remoção de dependências.](/learn/removing-effect-dependencies) --- -### Removing unnecessary function dependencies {/*removing-unnecessary-function-dependencies*/} +### Removendo funções desnecessárias das dependências {/*removing-unnecessary-function-dependencies*/} -If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every render because the `createOptions` function is [different for every render:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally) +Se seu effect depende de um objeto ou de uma função criados durante a renderização, ele pode executar com muita frequência. Por exemplo, este Effect reconecta após cada renderização, pois a função `createOptions` é [diferente para cada renderização:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally) ```js {4-9,12,16} function ChatRoom({ roomId }) { const [message, setMessage] = useState(''); - function createOptions() { // 🚩 This function is created from scratch on every re-render + function createOptions() { // 🚩 Esta função é recriada a cada rerenderização return { serverUrl: serverUrl, roomId: roomId @@ -1594,17 +1595,17 @@ function ChatRoom({ roomId }) { } useEffect(() => { - const options = createOptions(); // It's used inside the Effect + const options = createOptions(); // E usada dentro do Effect const connection = createConnection(); connection.connect(); return () => connection.disconnect(); - }, [createOptions]); // 🚩 As a result, these dependencies are always different on a re-render + }, [createOptions]); // 🚩 Como resultado, estas dependências são sempre diferentes numa rerenderização // ... ``` -By itself, creating a function from scratch on every re-render is not a problem. You don't need to optimize that. However, if you use it as a dependency of your Effect, it will cause your Effect to re-run after every re-render. +Recriar uma função a cada rerenderização em si não é um problema. Você não precisa otimizar isto. No entanto, se você a utiliza como uma dependência de seu Effect, isto irá fazer com que seu Effect seja reexecutado a cada rerenderização. -Avoid using a function created during rendering as a dependency. Instead, declare it inside the Effect: +Evite utilizar funções criadas durante a renderização como dependência. Ao invés disto, as declare dentro do Effect: @@ -1633,25 +1634,25 @@ function ChatRoom({ roomId }) { return ( <> -

    Welcome to the {roomId} room!

    +

    Bem-vindo à sala {roomId}!

    setMessage(e.target.value)} /> ); } export default function App() { - const [roomId, setRoomId] = useState('general'); + const [roomId, setRoomId] = useState('geral'); return ( <>
    @@ -1663,13 +1664,13 @@ export default function App() { ```js chat.js export function createConnection({ serverUrl, roomId }) { - // A real implementation would actually connect to the server + // Uma implementação real se conectaria ao servidor return { connect() { - console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...'); + console.log('✅ Conectando-se ao canal "' + roomId + '" em ' + serverUrl + '...'); }, disconnect() { - console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl); + console.log('❌ Desconectado do canal "' + roomId + '" em ' + serverUrl); } }; } @@ -1682,32 +1683,32 @@ button { margin-left: 10px; }
    -Now that you define the `createOptions` function inside the Effect, the Effect itself only depends on the `roomId` string. With this fix, typing into the input doesn't reconnect the chat. Unlike a function which gets re-created, a string like `roomId` doesn't change unless you set it to another value. [Read more about removing dependencies.](/learn/removing-effect-dependencies) +Agora que você definiu a função `createOptions` dentro do Effect, o Effect em si depende somente da string `roomId`. Com esta correção, escrever no campo de texto não causa reconexão ao chat. Diferentemente de uma função que é recriada, uma string como `roomId` não é modificada a não ser que você altere seu valor. [Leia mais sobre remoção de dependências.](/learn/removing-effect-dependencies) --- -### Reading the latest props and state from an Effect {/*reading-the-latest-props-and-state-from-an-effect*/} +### Lendo valores atualizados de props e state a partir de um Effect {/*reading-the-latest-props-and-state-from-an-effect*/} -This section describes an **experimental API that has not yet been released** in a stable version of React. +Esta seção descreve uma **API experimental que ainda não foi lançada** numa versão estável do React. -By default, when you read a reactive value from an Effect, you have to add it as a dependency. This ensures that your Effect "reacts" to every change of that value. For most dependencies, that's the behavior you want. +Por padrão, quando você lê um valor reativo de dentro de um Effect, você precisa adicioná-lo como uma dependência. Isto garante que seu Effect "reage" a cada mudança deste valor. Para a maioria das dependências, este é o comportamento que você quer. -**However, sometimes you'll want to read the *latest* props and state from an Effect without "reacting" to them.** For example, imagine you want to log the number of the items in the shopping cart for every page visit: +**No entanto, algumas vezes você irá querer ler o *último* valor de props e state dentro de um Effect, sem "reagir" a ele.** Por exemplo, imagine que você quer logar o número de itens no carrinho de compras a cada visita à página: ```js {3} function Page({ url, shoppingCart }) { useEffect(() => { logVisit(url, shoppingCart.length); - }, [url, shoppingCart]); // ✅ All dependencies declared + }, [url, shoppingCart]); // ✅ Todas dependências declaradas // ... } ``` -**What if you want to log a new page visit after every `url` change, but *not* if only the `shoppingCart` changes?** You can't exclude `shoppingCart` from dependencies without breaking the [reactivity rules.](#specifying-reactive-dependencies) However, you can express that you *don't want* a piece of code to "react" to changes even though it is called from inside an Effect. [Declare an *Effect Event*](/learn/separating-events-from-effects#declaring-an-effect-event) with the [`useEffectEvent`](/reference/react/experimental_useEffectEvent) Hook, and move the code reading `shoppingCart` inside of it: +**E se você quiser logar uma visita a uma página nova a cada mudança em `url`, mas *não* se somente `shoppingCart` for atualizado?** Você não pode excluir `shoppingCart` das dependências sem quebrar as [regras de reatividade.](#specifying-reactive-dependencies) No entanto, você pode expressar que você *não quer* que uma parte do código "reaja" a mudanças, mesmo que seja chamado de dentro de um Effect. [Declare um *Effect Event*](/learn/separating-events-from-effects#declaring-an-effect-event) com o Hook [`useEffectEvent`](/reference/react/experimental_useEffectEvent), e move o código lendo `shoppingCart` para dentro dele: ```js {2-4,7,8} function Page({ url, shoppingCart }) { @@ -1717,23 +1718,23 @@ function Page({ url, shoppingCart }) { useEffect(() => { onVisit(url); - }, [url]); // ✅ All dependencies declared + }, [url]); // ✅ Todas dependências declaradas // ... } ``` -**Effect Events are not reactive and must always be omitted from dependencies of your Effect.** This is what lets you put non-reactive code (where you can read the latest value of some props and state) inside of them. By reading `shoppingCart` inside of `onVisit`, you ensure that `shoppingCart` won't re-run your Effect. +**Effect Events não são reativos e devem sempre ser omitidos das dependências de seu Effect.** É isto que permite que você coloque código não-reativo (onde você pode ler o último valor de props e state) dentro deles. Ao ler `shoppingCart` dentro de `onVisit`, você garante que `shoppingCart` não reexecutará seu Effect. -[Read more about how Effect Events let you separate reactive and non-reactive code.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events) +[Leia mais sobre como Effect Events permitem que você separe código reativo de não-reativo.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events) --- -### Displaying different content on the server and the client {/*displaying-different-content-on-the-server-and-the-client*/} +### Exibindo conteúdos diferentes no servidor e no cliente {/*displaying-different-content-on-the-server-and-the-client*/} -If your app uses server rendering (either [directly](/reference/react-dom/server) or via a [framework](/learn/start-a-new-react-project#production-grade-react-frameworks)), your component will render in two different environments. On the server, it will render to produce the initial HTML. On the client, React will run the rendering code again so that it can attach your event handlers to that HTML. This is why, for [hydration](/reference/react-dom/client/hydrateRoot#hydrating-server-rendered-html) to work, your initial render output must be identical on the client and the server. +Se sua aplicação usa renderização do lado do servidor (tanto [diretamente](/reference/react-dom/server) quanto via um [framework](/learn/start-a-new-react-project#production-grade-react-frameworks)), seu componente irá renderizar em dois ambientes diferentes. No servidor, ela irá renderizar para produzir o HTML inicial. No cliente, o React irá executar o código de renderização novamente para poder anexar seus event handlers àquele HTML. É por isto que, para que o [hydration](/reference/react-dom/client/hydrateRoot#hydrating-server-rendered-html) funcione, o resultado de sua renderização inicial precisa ser idêntico entre servidor e cliente. -In rare cases, you might need to display different content on the client. For example, if your app reads some data from [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), it can't possibly do that on the server. Here is how you could implement this: +Em raros casos, você pode precisar exibir conteúdo diferente no lado do cliente. Por exemplo, se sua aplicação lê algum dado de [`localStorage`](https://developer.mozilla.org/pt-BR/docs/Web/API/Window/localStorage), não é possível fazer isto do lado do servidor. Eis um modo de implementar isto: ```js function MyComponent() { @@ -1744,44 +1745,44 @@ function MyComponent() { }, []); if (didMount) { - // ... return client-only JSX ... + // ... retorne JSX somente para cliente... } else { - // ... return initial JSX ... + // ... retorne o JSX inicial... } } ``` -While the app is loading, the user will see the initial render output. Then, when it's loaded and hydrated, your Effect will run and set `didMount` to `true`, triggering a re-render. This will switch to the client-only render output. Effects don't run on the server, so this is why `didMount` was `false` during the initial server render. +Enquanto a aplicação está carregando, o usuário irá ver a saída inicial da renderização. Então, após o carregamento e execução do hydration, seu Effect irá executar e definir `didMount` como `true`, causando uma rerenderização. Isto irá alternar para a renderização do lado do cliente. Effects não são executados no servidor, e é por isso que `didMount` era `false` durante a renderização inicial do lado do servidor. -Use this pattern sparingly. Keep in mind that users with a slow connection will see the initial content for quite a bit of time--potentially, many seconds--so you don't want to make jarring changes to your component's appearance. In many cases, you can avoid the need for this by conditionally showing different things with CSS. +Use este modelo com moderação. Lembre-se de que usuários com conexões lentas irão ver o conteúdo inicial por um bom tempo -- potencialmente vários segundos -- portanto você não vai querer que seu componente altere sua aparência de forma tão drástica. Em vários casos, você pode evitar esta solução utilizando CSS para exibir condicionalmente elementos distintos. --- -## Troubleshooting {/*troubleshooting*/} +## Solução de problemas {/*troubleshooting*/} -### My Effect runs twice when the component mounts {/*my-effect-runs-twice-when-the-component-mounts*/} +### Meu Effect roda duas vezes quando o componente monta {/*my-effect-runs-twice-when-the-component-mounts*/} -When Strict Mode is on, in development, React runs setup and cleanup one extra time before the actual setup. +Quando o Strict Mode está ativado, em desenvolvimento, o React roda as funções de setup e cleanup uma vez a mais antes da execução verdadeira do setup. -This is a stress-test that verifies your Effect’s logic is implemented correctly. If this causes visible issues, your cleanup function is missing some logic. The cleanup function should stop or undo whatever the setup function was doing. The rule of thumb is that the user shouldn’t be able to distinguish between the setup being called once (as in production) and a setup → cleanup → setup sequence (as in development). +Este é um teste que verifica se a lógica do seu Effect está implementada corretamente. Se isto causar problemas, alguma lógica está faltando na sua função de cleanup. A função de cleanup deveria parar e desfazer qualquer coisa que a função de setup estava fazendo. De maneira geral, o usuário não deveria poder diferenciar se o setup está sendo chamado uma só vez (como em produção) ou numa sequência *setup* → *cleanup* → *setup* (como em desenvolvimento). -Read more about [how this helps find bugs](/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed) and [how to fix your logic.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) +Leia mais sobre [como isto ajuda a encontrar erros](/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed) e [como corrigir sua lógica.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development) --- -### My Effect runs after every re-render {/*my-effect-runs-after-every-re-render*/} +### Meu Effect executa após cada rerenderização {/*my-effect-runs-after-every-re-render*/} -First, check that you haven't forgotten to specify the dependency array: +Primeiro, verifique se você não esqueceu de especificar a lista de dependências: ```js {3} useEffect(() => { // ... -}); // 🚩 No dependency array: re-runs after every render! +}); // 🚩 Sem lista de dependência: reexecuta após cada renderização! ``` -If you've specified the dependency array but your Effect still re-runs in a loop, it's because one of your dependencies is different on every re-render. +Se você especificou a lista de dependências mas seu Effect ainda reexecuta em loop, é porque uma de suas dependências é diferente em cada rerenderização. -You can debug this problem by manually logging your dependencies to the console: +Você pode depurar este problema manualmente logando suas dependências no console: ```js {5} useEffect(() => { @@ -1791,58 +1792,58 @@ You can debug this problem by manually logging your dependencies to the console: console.log([serverUrl, roomId]); ``` -You can then right-click on the arrays from different re-renders in the console and select "Store as a global variable" for both of them. Assuming the first one got saved as `temp1` and the second one got saved as `temp2`, you can then use the browser console to check whether each dependency in both arrays is the same: +Você pode então clicar com o botão direito do mouse nas listas de diferentes rerenderizações e selecionar "Store as a global variable" para ambos. Assumindo que o primeiro foi salvo como `temp1` e o segundo como `temp2`, você pode utilizar o console do navegador para verificar se cada dependência em ambas as listas é a mesma: ```js -Object.is(temp1[0], temp2[0]); // Is the first dependency the same between the arrays? -Object.is(temp1[1], temp2[1]); // Is the second dependency the same between the arrays? -Object.is(temp1[2], temp2[2]); // ... and so on for every dependency ... +Object.is(temp1[0], temp2[0]); // A primeira dependência é a mesma em ambas as listas? +Object.is(temp1[1], temp2[1]); // A segunda dependência é a mesma em ambas as listas? +Object.is(temp1[2], temp2[2]); // ... e por aí vai, para cada dependência ... ``` -When you find the dependency that is different on every re-render, you can usually fix it in one of these ways: +Quando você encontrar a dependência que difere em rerenderizações, você geralmente pode consertar isto de um destes modos: -- [Updating state based on previous state from an Effect](#updating-state-based-on-previous-state-from-an-effect) -- [Removing unnecessary object dependencies](#removing-unnecessary-object-dependencies) -- [Removing unnecessary function dependencies](#removing-unnecessary-function-dependencies) -- [Reading the latest props and state from an Effect](#reading-the-latest-props-and-state-from-an-effect) +- [Atualizando state baseado em valores anteriores num Effect](#updating-state-based-on-previous-state-from-an-effect) +- [Removendo objetos desnecessários das dependências](#removing-unnecessary-object-dependencies) +- [Removendo funções desnecessárias das dependências](#removing-unnecessary-function-dependencies) +- [Lendo valores atualizados de props e state a partir de um Effect](#reading-the-latest-props-and-state-from-an-effect) -As a last resort (if these methods didn't help), wrap its creation with [`useMemo`](/reference/react/useMemo#memoizing-a-dependency-of-another-hook) or [`useCallback`](/reference/react/useCallback#preventing-an-effect-from-firing-too-often) (for functions). +Em última instância (se nenhum destes métodos ajudar), encapsule sua criação com [`useMemo`](/reference/react/useMemo#memoizing-a-dependency-of-another-hook) ou [`useCallback`](/reference/react/useCallback#preventing-an-effect-from-firing-too-often) (para funções). --- -### My Effect keeps re-running in an infinite cycle {/*my-effect-keeps-re-running-in-an-infinite-cycle*/} +### Meu Effect executa em ciclo infinito {/*my-effect-keeps-re-running-in-an-infinite-cycle*/} -If your Effect runs in an infinite cycle, these two things must be true: +Se seu Effect executa em um ciclo infinito, estas duas coisas devem estar acontecendo: -- Your Effect is updating some state. -- That state leads to a re-render, which causes the Effect's dependencies to change. +- Seu Effect está atualizando algum state. +- Este state causa um rerender, fazendo com que as dependências do Effect mudem. -Before you start fixing the problem, ask yourself whether your Effect is connecting to some external system (like DOM, network, a third-party widget, and so on). Why does your Effect need to set state? Does it synchronize with that external system? Or are you trying to manage your application's data flow with it? +Antes de começar a arrumar este problema, pergunte a si mesmo se este Effect está se conectando a um sistema externo (como o DOM, a rede, um widget de terceiros, etc.). Por que seu Effect precisa alterar o state? Ele se sincroniza com este sistema externo? Ou você está tentando gerenciar o fluxo de dados da sua aplicação com ele? -If there is no external system, consider whether [removing the Effect altogether](/learn/you-might-not-need-an-effect) would simplify your logic. +Se não há sistema externo, considere se [a remoção completa do Effect](/learn/you-might-not-need-an-effect) simplificaria sua lógica. -If you're genuinely synchronizing with some external system, think about why and under what conditions your Effect should update the state. Has something changed that affects your component's visual output? If you need to keep track of some data that isn't used by rendering, a [ref](/reference/react/useRef#referencing-a-value-with-a-ref) (which doesn't trigger re-renders) might be more appropriate. Verify your Effect doesn't update the state (and trigger re-renders) more than needed. +Se você está genuinamente sincronizando com algum sistema externo, pense sobre a razão e sobre quais condições seu Effect deveria atualizar o state. Algo que afeta a saída visual do seu componente foi alterado? Se você precisa manter controle sobre algum dado que não é utilizado para renderização, um [ref](/reference/react/useRef#referencing-a-value-with-a-ref) (que não causa rerenderizações) pode ser apropriado. Verifique que seu Effect não atualiza o state (e causa rerenderização) mais que o necessário. -Finally, if your Effect is updating the state at the right time, but there is still a loop, it's because that state update leads to one of the Effect's dependencies changing. [Read how to debug dependency changes.](/reference/react/useEffect#my-effect-runs-after-every-re-render) +Finalmente, se seu Effect está atualizando o state no momento certo, mas ainda há um ciclo, é porque a atualização deste state faz com que as dependências de outro Effect sejam atualizadas. --- -### My cleanup logic runs even though my component didn't unmount {/*my-cleanup-logic-runs-even-though-my-component-didnt-unmount*/} +### Minha lógica de cleanup é executada mesmo que meu componente não tenha desmontado {/*my-cleanup-logic-runs-even-though-my-component-didnt-unmount*/} -The cleanup function runs not only during unmount, but before every re-render with changed dependencies. Additionally, in development, React [runs setup+cleanup one extra time immediately after component mounts.](#my-effect-runs-twice-when-the-component-mounts) +A função de cleanup é executada não somente durante a desmontagem, mas antes de cada rerenderização com dependências atualizadas. Adicionalmente, em desenvolvimento, o React [executa um ciclo extra de setup+cleanup imediatamente após a montagem do componente.](#my-effect-runs-twice-when-the-component-mounts) -If you have cleanup code without corresponding setup code, it's usually a code smell: +Se você possui código de cleanup sem um código de setup correspondente, isto é geralmente um mau sinal: ```js {2-5} useEffect(() => { - // 🔴 Avoid: Cleanup logic without corresponding setup logic + // 🔴 Evite: lógica de cleanup sem lógica de setup correspondente return () => { doSomething(); }; }, []); ``` -Your cleanup logic should be "symmetrical" to the setup logic, and should stop or undo whatever setup did: +Sua lógica de cleanup deveria ser "simétrica" à lógica de setup, e deveria parar ou desfazer qualquer coisa que o setup tenha feito: ```js {2-3,5} useEffect(() => { @@ -1854,10 +1855,14 @@ Your cleanup logic should be "symmetrical" to the setup logic, and should stop o }, [serverUrl, roomId]); ``` -[Learn how the Effect lifecycle is different from the component's lifecycle.](/learn/lifecycle-of-reactive-effects#the-lifecycle-of-an-effect) +[Aprenda como o ciclo de vida de Effect é diferente do ciclo de vida do componente.](/learn/lifecycle-of-reactive-effects#the-lifecycle-of-an-effect) --- -### My Effect does something visual, and I see a flicker before it runs {/*my-effect-does-something-visual-and-i-see-a-flicker-before-it-runs*/} +### Meu Effect faz algo visual, e vejo tremulações antes de sua execução {/*my-effect-does-something-visual-and-i-see-a-flicker-before-it-runs*/} + +* Se seu Effect não foi causado por uma interação (como um clique), o React deixará o navegador **pintar a tela atualizada antes de executar seu Effect.** Caso seu Effect esteja fazendo algo visual (por exemplo, posicionando um tooltip) e o atraso for perceptível (causando, por exemplo, tremulações), substitua `useEffect` por [`useLayoutEffect`.](/reference/react/useLayoutEffect) + +* Mesmo que seu Effect tenha sido causado por uma interação (como um clique), **o navegador pode repintar a tela antes de processar atualizações de state dentro de seu Effect.** Normalmente, é isto que você quer. No entanto, se você precisar impedir o navegador de repintar a tela, você precisará substituir `useEffect` por [`useLayoutEffect`.](/reference/react/useLayoutEffect) -If your Effect must block the browser from [painting the screen,](/learn/render-and-commit#epilogue-browser-paint) replace `useEffect` with [`useLayoutEffect`](/reference/react/useLayoutEffect). Note that **this shouldn't be needed for the vast majority of Effects.** You'll only need this if it's crucial to run your Effect before the browser paint: for example, to measure and position a tooltip before the user sees it. +Se seu Effect precisar impedir o navegador de [pintar a tela,](/learn/render-and-commit#epilogue-browser-paint) substitua `useEffect` por [`useLayoutEffect`](/reference/react/useLayoutEffect). Perceba que **isto não deveria ser necessário para a grande maioria dos Effects.** Você só precisará disto se for crucial executar seu Effect antes que o navegador pinte a tela: por exemplo, para medir a posição de um tooltip antes que o usuário o veja.