diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index 2d44d7353..2f65f1e35 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -1,52 +1,52 @@ --- -title: 'Manipulating the DOM with Refs' +title: 'Manipulando o DOM com Refs' --- -React automatically updates the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) to match your render output, so your components won't often need to manipulate it. However, sometimes you might need access to the DOM elements managed by React--for example, to focus a node, scroll to it, or measure its size and position. There is no built-in way to do those things in React, so you will need a *ref* to the DOM node. +O React atualiza automaticamente o [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) para corresponder à sua saída de renderização, então seus componentes não precisarão frequentemente manipulá-lo. No entanto, às vezes você pode precisar de acesso aos elementos DOM gerenciados pelo React—por exemplo, para focar um nó, rolar para ele ou medir seu tamanho e posição. Não há uma maneira integrada de fazer essas coisas no React, então você precisará de um *ref* para o nó do DOM. -- How to access a DOM node managed by React with the `ref` attribute -- How the `ref` JSX attribute relates to the `useRef` Hook -- How to access another component's DOM node -- In which cases it's safe to modify the DOM managed by React +- Como acessar um nó do DOM gerenciado pelo React com o atributo `ref` +- Como o atributo JSX `ref` se relaciona ao Hook `useRef` +- Como acessar o nó do DOM de outro componente +- Em quais casos é seguro modificar o DOM gerenciado pelo React -## Getting a ref to the node {/*getting-a-ref-to-the-node*/} +## Obtendo um ref para o nó {/*getting-a-ref-to-the-node*/} -To access a DOM node managed by React, first, import the `useRef` Hook: +Para acessar um nó do DOM gerenciado pelo React, primeiro importe o Hook `useRef`: ```js import { useRef } from 'react'; ``` -Then, use it to declare a ref inside your component: +Em seguida, use-o para declarar um ref dentro do seu componente: ```js const myRef = useRef(null); ``` -Finally, pass your ref as the `ref` attribute to the JSX tag for which you want to get the DOM node: +Finalmente, passe seu ref como o atributo `ref` para a tag JSX da qual você deseja obter o nó do DOM: ```js
``` -The `useRef` Hook returns an object with a single property called `current`. Initially, `myRef.current` will be `null`. When React creates a DOM node for this `
`, React will put a reference to this node into `myRef.current`. You can then access this DOM node from your [event handlers](/learn/responding-to-events) and use the built-in [browser APIs](https://developer.mozilla.org/docs/Web/API/Element) defined on it. +O Hook `useRef` retorna um objeto com uma única propriedade chamada `current`. Inicialmente, `myRef.current` será `null`. Quando o React criar um nó do DOM para este `
`, o React colocará uma referência a este nó em `myRef.current`. Você poderá então acessar este nó do DOM de seus [manipuladores de eventos](/learn/responding-to-events) e usar as [APIs de navegador](https://developer.mozilla.org/docs/Web/API/Element) integradas definidas nele. ```js -// You can use any browser APIs, for example: +// Você pode usar qualquer API de navegador, por exemplo: myRef.current.scrollIntoView(); ``` -### Example: Focusing a text input {/*example-focusing-a-text-input*/} +### Exemplo: Focando um campo de texto {/*example-focusing-a-text-input*/} -In this example, clicking the button will focus the input: +Neste exemplo, clicar no botão irá focar a entrada: @@ -64,7 +64,7 @@ export default function Form() { <> ); @@ -73,18 +73,18 @@ export default function Form() { -To implement this: +Para implementar isso: -1. Declare `inputRef` with the `useRef` Hook. -2. Pass it as ``. This tells React to **put this ``'s DOM node into `inputRef.current`.** -3. In the `handleClick` function, read the input DOM node from `inputRef.current` and call [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on it with `inputRef.current.focus()`. -4. Pass the `handleClick` event handler to ` ); @@ -400,17 +400,17 @@ export default function MyForm() { -To help you notice the issue, React also prints an error to the console: +Para ajudá-lo a notar o problema, o React também imprime um erro no console: -Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? +Aviso: Componentes de função não podem receber refs. Tentativas de acessar este ref falharão. Você quis dizer para usar React.forwardRef()? -This happens because by default React does not let a component access the DOM nodes of other components. Not even for its own children! This is intentional. Refs are an escape hatch that should be used sparingly. Manually manipulating _another_ component's DOM nodes makes your code even more fragile. +Isso acontece porque, por padrão, o React não permite que um componente acesse os nós DOM de outros componentes. Nem mesmo para seus próprios filhos! Isso é intencional. Os refs são uma escapatória que deve ser usada com moderação. Manipular manualmente os nós DOM de _outro_ componente torna seu código ainda mais frágil. -Instead, components that _want_ to expose their DOM nodes have to **opt in** to that behavior. A component can specify that it "forwards" its ref to one of its children. Here's how `MyInput` can use the `forwardRef` API: +Em vez disso, componentes que _querem_ expor seus nós DOM devem **optar** por esse comportamento. Um componente pode especificar que "encaminha" seu ref para um de seus filhos. Aqui está como `MyInput` pode usar a API `forwardRef`: ```js const MyInput = forwardRef((props, ref) => { @@ -418,13 +418,13 @@ const MyInput = forwardRef((props, ref) => { }); ``` -This is how it works: +Assim funciona: -1. `` tells React to put the corresponding DOM node into `inputRef.current`. However, it's up to the `MyInput` component to opt into that--by default, it doesn't. -2. The `MyInput` component is declared using `forwardRef`. **This opts it into receiving the `inputRef` from above as the second `ref` argument** which is declared after `props`. -3. `MyInput` itself passes the `ref` it received to the `` inside of it. +1. `` diz ao React para colocar o nó DOM correspondente em `inputRef.current`. No entanto, cabe ao componente `MyInput` optar por isso—por padrão, ele não faz. +2. O componente `MyInput` é declarado usando `forwardRef`. **Isso o opta para receber o `inputRef` de cima como o segundo argumento `ref`** que é declarado após `props`. +3. O `MyInput` em si passa o `ref` que recebeu para o `` dentro dele. -Now clicking the button to focus the input works: +Agora, clicar no botão para focar a entrada funciona: @@ -446,7 +446,7 @@ export default function Form() { <> ); @@ -455,13 +455,13 @@ export default function Form() { -In design systems, it is a common pattern for low-level components like buttons, inputs, and so on, to forward their refs to their DOM nodes. On the other hand, high-level components like forms, lists, or page sections usually won't expose their DOM nodes to avoid accidental dependencies on the DOM structure. +Em sistemas de design, é um padrão comum que componentes de baixo nível, como botões, entradas e assim por diante, encaminhem seus refs para seus nós DOM. Por outro lado, componentes de alto nível, como formulários, listas ou seções de página, geralmente não expõem seus nós DOM para evitar dependências acidentais na estrutura DOM. -#### Exposing a subset of the API with an imperative handle {/*exposing-a-subset-of-the-api-with-an-imperative-handle*/} +#### Expondo um subconjunto da API com uma handle imperativa {/*exposing-a-subset-of-the-api-with-an-imperative-handle*/} -In the above example, `MyInput` exposes the original DOM input element. This lets the parent component call `focus()` on it. However, this also lets the parent component do something else--for example, change its CSS styles. In uncommon cases, you may want to restrict the exposed functionality. You can do that with `useImperativeHandle`: +No exemplo acima, `MyInput` expõe o elemento DOM de entrada original. Isso permite que o componente pai chame `focus()` nele. No entanto, isso também permite que o componente pai faça algo mais—por exemplo, alterar seus estilos CSS. Em casos não comuns, você pode querer restringir a funcionalidade exposta. Você pode fazer isso com `useImperativeHandle`: @@ -475,7 +475,7 @@ import { const MyInput = forwardRef((props, ref) => { const realInputRef = useRef(null); useImperativeHandle(ref, () => ({ - // Only expose focus and nothing else + // Apenas expõe foco e mais nada focus() { realInputRef.current.focus(); }, @@ -494,7 +494,7 @@ export default function Form() { <> ); @@ -503,28 +503,28 @@ export default function Form() { -Here, `realInputRef` inside `MyInput` holds the actual input DOM node. However, `useImperativeHandle` instructs React to provide your own special object as the value of a ref to the parent component. So `inputRef.current` inside the `Form` component will only have the `focus` method. In this case, the ref "handle" is not the DOM node, but the custom object you create inside `useImperativeHandle` call. +Aqui, `realInputRef` dentro de `MyInput` contém o nó DOM de entrada real. No entanto, `useImperativeHandle` instrui o React a fornecer seu próprio objeto especial como o valor de um ref para o componente pai. Assim, `inputRef.current` dentro do componente `Form` terá apenas o método `focus`. Nesse caso, a "handle" do ref não é o nó DOM, mas o objeto customizado que você cria dentro da chamada `useImperativeHandle`. -## When React attaches the refs {/*when-react-attaches-the-refs*/} +## Quando o React anexa os refs {/*when-react-attaches-the-refs*/} -In React, every update is split in [two phases](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom): +No React, cada atualização é dividida em [duas fases](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom): -* During **render,** React calls your components to figure out what should be on the screen. -* During **commit,** React applies changes to the DOM. +* Durante a **renderização,** o React chama seus componentes para descobrir o que deve estar na tela. +* Durante o **compromisso,** o React aplica as alterações ao DOM. -In general, you [don't want](/learn/referencing-values-with-refs#best-practices-for-refs) to access refs during rendering. That goes for refs holding DOM nodes as well. During the first render, the DOM nodes have not yet been created, so `ref.current` will be `null`. And during the rendering of updates, the DOM nodes haven't been updated yet. So it's too early to read them. +Em geral, você [não quer](/learn/referencing-values-with-refs#best-practices-for-refs) acessar refs durante a renderização. Isso se aplica a refs que contêm nós DOM também. Durante a primeira renderização, os nós DOM ainda não foram criados, então `ref.current` será `null`. E durante a renderização das atualizações, os nós DOM ainda não foram atualizados. Portanto, é cedo demais para lê-los. -React sets `ref.current` during the commit. Before updating the DOM, React sets the affected `ref.current` values to `null`. After updating the DOM, React immediately sets them to the corresponding DOM nodes. +O React define `ref.current` durante o compromisso. Antes de atualizar o DOM, o React define os valores afetados de `ref.current` como `null`. Após atualizar o DOM, o React imediatamente os define para os nós DOM correspondentes. -**Usually, you will access refs from event handlers.** If you want to do something with a ref, but there is no particular event to do it in, you might need an Effect. We will discuss Effects on the next pages. +**Geralmente, você acessará refs a partir de manipuladores de eventos.** Se você quiser fazer algo com um ref, mas não houver um evento específico para fazê-lo, pode precisar de um Effect. Vamos discutir Effects nas próximas páginas. -#### Flushing state updates synchronously with flushSync {/*flushing-state-updates-synchronously-with-flush-sync*/} +#### Limpando atualizações de estado de forma síncrona com flushSync {/*flushing-state-updates-synchronously-with-flush-sync*/} -Consider code like this, which adds a new todo and scrolls the screen down to the last child of the list. Notice how, for some reason, it always scrolls to the todo that was *just before* the last added one: +Considere um código como este, que adiciona uma nova tarefa e rola a tela para o último filho da lista. Note como, por algum motivo, ele sempre rola para a tarefa que foi *apenas antes* da última adicionada: @@ -551,7 +551,7 @@ export default function TodoList() { return ( <> -The issue is with these two lines: +O problema está nessas duas linhas: ```js setTodos([ ...todos, newTodo]); listRef.current.lastChild.scrollIntoView(); ``` -In React, [state updates are queued.](/learn/queueing-a-series-of-state-updates) Usually, this is what you want. However, here it causes a problem because `setTodos` does not immediately update the DOM. So the time you scroll the list to its last element, the todo has not yet been added. This is why scrolling always "lags behind" by one item. +No React, [atualizações de estado são enfileiradas.](/learn/queueing-a-series-of-state-updates) Normalmente, isso é o que você deseja. No entanto, aqui isso causa um problema porque `setTodos` não atualiza imediatamente o DOM. Então, no momento em que você rola a lista para seu último elemento, a tarefa ainda não foi adicionada. É por isso que a rolagem sempre "atrasada" em um item. -To fix this issue, you can force React to update ("flush") the DOM synchronously. To do this, import `flushSync` from `react-dom` and **wrap the state update** into a `flushSync` call: +Para corrigir esse problema, você pode forçar o React a atualizar ("limpar") o DOM de forma síncrona. Para fazer isso, importe `flushSync` de `react-dom` e **envelope a atualização de estado** em uma chamada `flushSync`: ```js flushSync(() => { @@ -596,7 +596,7 @@ flushSync(() => { listRef.current.lastChild.scrollIntoView(); ``` -This will instruct React to update the DOM synchronously right after the code wrapped in `flushSync` executes. As a result, the last todo will already be in the DOM by the time you try to scroll to it: +Isso instruirá o React a atualizar o DOM de forma síncrona logo após a execução do código envolvido na chamada `flushSync`. Como resultado, a última tarefa já estará no DOM no momento em que você tentar rolar para ela: @@ -626,7 +626,7 @@ export default function TodoList() { return ( <> -## Best practices for DOM manipulation with refs {/*best-practices-for-dom-manipulation-with-refs*/} +## Melhores práticas para manipulação do DOM com refs {/*best-practices-for-dom-manipulation-with-refs*/} -Refs are an escape hatch. You should only use them when you have to "step outside React". Common examples of this include managing focus, scroll position, or calling browser APIs that React does not expose. +Refs são uma escapatória. Você só deve usá-los quando precisar "sair do React". Exemplos comuns disso incluem gerenciar foco, posição de rolagem, ou chamar APIs de navegador que o React não expõe. -If you stick to non-destructive actions like focusing and scrolling, you shouldn't encounter any problems. However, if you try to **modify** the DOM manually, you can risk conflicting with the changes React is making. +Se você se limitar a ações não destrutivas, como focar e rolar, não deverá encontrar problemas. No entanto, se você tentar **modificar** o DOM manualmente, pode correr o risco de conflitar com as alterações que o React está fazendo. -To illustrate this problem, this example includes a welcome message and two buttons. The first button toggles its presence using [conditional rendering](/learn/conditional-rendering) and [state](/learn/state-a-components-memory), as you would usually do in React. The second button uses the [`remove()` DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Element/remove) to forcefully remove it from the DOM outside of React's control. +Para ilustrar esse problema, este exemplo inclui uma mensagem de boas-vindas e dois botões. O primeiro botão alterna sua presença usando [renderização condicional](/learn/conditional-rendering) e [estado](/learn/state-a-components-memory), como você normalmente faria no React. O segundo botão usa a [API DOM `remove()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/remove) para removê-lo à força do DOM fora do controle do React. -Try pressing "Toggle with setState" a few times. The message should disappear and appear again. Then press "Remove from the DOM". This will forcefully remove it. Finally, press "Toggle with setState": +Tente pressionar "Alternar com setState" algumas vezes. A mensagem deve desaparecer e aparecer novamente. Em seguida, pressione "Remover do DOM". Isso o removerá à força. Finalmente, pressione "Alternar com setState": @@ -680,15 +680,15 @@ export default function Counter() { onClick={() => { setShow(!show); }}> - Toggle with setState + Alternar com setState - {show &&

Hello world

} + {show &&

Olá mundo

}
); } @@ -704,30 +704,28 @@ button { -After you've manually removed the DOM element, trying to use `setState` to show it again will lead to a crash. This is because you've changed the DOM, and React doesn't know how to continue managing it correctly. +Depois de você remover manualmente o elemento DOM, tentar usar `setState` para mostrá-lo novamente resultará em uma falha. Isso acontece porque você mudou o DOM, e o React não sabe como continuar gerenciando-o corretamente. -**Avoid changing DOM nodes managed by React.** Modifying, adding children to, or removing children from elements that are managed by React can lead to inconsistent visual results or crashes like above. +**Evite mudar nós DOM gerenciados pelo React.** Modificar, adicionar filhos a, ou remover filhos de elementos que são gerenciados pelo React pode levar a resultados visuais inconsistentes ou falhas como a acima. -However, this doesn't mean that you can't do it at all. It requires caution. **You can safely modify parts of the DOM that React has _no reason_ to update.** For example, if some `
` is always empty in the JSX, React won't have a reason to touch its children list. Therefore, it is safe to manually add or remove elements there. +No entanto, isso não significa que você não possa fazê-lo. Isso requer cautela. **Você pode modificar partes do DOM que o React _não tem razão_ para atualizar com segurança.** Por exemplo, se algum `
` estiver sempre vazio no JSX, o React não terá razão para tocar em sua lista de filhos. Portanto, é seguro adicionar ou remover elementos manualmente lá. -- Refs are a generic concept, but most often you'll use them to hold DOM elements. -- You instruct React to put a DOM node into `myRef.current` by passing `
`. -- Usually, you will use refs for non-destructive actions like focusing, scrolling, or measuring DOM elements. -- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using `forwardRef` and passing the second `ref` argument down to a specific node. -- Avoid changing DOM nodes managed by React. -- If you do modify DOM nodes managed by React, modify parts that React has no reason to update. +- Refs são um conceito genérico, mas na maioria das vezes você os usará para manter elementos DOM. +- Você instrui o React a colocar um nó DOM em `myRef.current` passando `
`. +- Geralmente, você usará refs para ações não destrutivas como focar, rolar ou medir elementos DOM. +- Um componente não expõe seus nós DOM por padrão. Você pode optar por expor um nó DOM usando `forwardRef` e passando o segundo argumento `ref` para baixo para um nó específico. +- Evite mudar nós DOM gerenciados pelo React. +- Se você modificar nós DOM gerenciados pelo React, modifique partes que o React não tenha razão para atualizar. - - -#### Play and pause the video {/*play-and-pause-the-video*/} +#### Reproduzir e pausar o vídeo {/*play-and-pause-the-video*/} -In this example, the button toggles a state variable to switch between a playing and a paused state. However, in order to actually play or pause the video, toggling state is not enough. You also need to call [`play()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play) and [`pause()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause) on the DOM element for the `