From 02032b0a233f7de224cabede3c32da83bffc78c1 Mon Sep 17 00:00:00 2001 From: Nivaldo Farias Date: Thu, 20 Mar 2025 12:06:08 -0300 Subject: [PATCH 1/2] Translate `useMemo.md` to Portuguese --- src/content/reference/react/useMemo.md | 304 ++++++++++++------------- 1 file changed, 150 insertions(+), 154 deletions(-) diff --git a/src/content/reference/react/useMemo.md b/src/content/reference/react/useMemo.md index 6bfaba8ee..268b9202e 100644 --- a/src/content/reference/react/useMemo.md +++ b/src/content/reference/react/useMemo.md @@ -4,7 +4,7 @@ title: useMemo -`useMemo` is a React Hook that lets you cache the result of a calculation between re-renders. +`useMemo` é um Hook do React que permite que você armazene em cache o resultado de um cálculo entre as renderizações. ```js const cachedValue = useMemo(calculateValue, dependencies) @@ -16,11 +16,11 @@ const cachedValue = useMemo(calculateValue, dependencies) --- -## Reference {/*reference*/} +## Referência {/*reference*/} ### `useMemo(calculateValue, dependencies)` {/*usememo*/} -Call `useMemo` at the top level of your component to cache a calculation between re-renders: +Chame `useMemo` no nível superior do seu componente para armazenar em cache um cálculo entre as renderizações: ```js import { useMemo } from 'react'; @@ -34,39 +34,39 @@ function TodoList({ todos, tab }) { } ``` -[See more examples below.](#usage) +[Veja mais exemplos abaixo.](#usage) -#### Parameters {/*parameters*/} +#### Parâmetros {/*parameters*/} -* `calculateValue`: The function calculating the value that you want to cache. It should be pure, should take no arguments, and should return a value of any type. React will call your function during the initial render. On next renders, React will return the same value again if the `dependencies` have not changed since the last render. Otherwise, it will call `calculateValue`, return its result, and store it so it can be reused later. +* `calculateValue`: A função que calcula o valor que você quer armazenar em cache. Ela deve ser pura, não deve receber argumentos e deve retornar um valor de qualquer tipo. O React chamará sua função durante a renderização inicial. Nas renderizações seguintes, o React retornará o mesmo valor novamente se as `dependencies` não tiverem mudado desde a última renderização. Caso contrário, ele chamará `calculateValue`, retornará seu resultado e o armazenará para que possa ser reutilizado mais tarde. -* `dependencies`: The list of all reactive values referenced inside of the `calculateValue` 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. +* `dependencies`: A lista de todos os valores reativos referenciados dentro do código `calculateValue`. 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 verificará se cada valor reativo é especificado corretamente como uma dependência. A lista de dependências deve ter um número constante de itens e ser escrita inline, como `[dep1, dep2, dep3]`. O React 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). -#### Returns {/*returns*/} +#### Retorna {/*returns*/} -On the initial render, `useMemo` returns the result of calling `calculateValue` with no arguments. +Na renderização inicial, `useMemo` retorna o resultado de chamar `calculateValue` sem argumentos. -During next renders, it will either return an already stored value from the last render (if the dependencies haven't changed), or call `calculateValue` again, and return the result that `calculateValue` has returned. +Durante as próximas renderizações, ele retornará um valor já armazenado da última renderização (se as dependências não tiverem mudado) ou chamará `calculateValue` novamente e retornará o resultado que `calculateValue` retornou. -#### Caveats {/*caveats*/} +#### Ressalvas {/*caveats*/} -* `useMemo` 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. -* In Strict Mode, React will **call your calculation function twice** in order to [help you find accidental impurities.](#my-calculation-runs-twice-on-every-re-render) This is development-only behavior and does not affect production. If your calculation function is pure (as it should be), this should not affect your logic. The result from one of the calls will be ignored. -* React **will not throw away the cached value unless there is a specific reason to do that.** For example, in development, React throws away the cache when you edit the file of your component. Both in development and in production, React will throw away the cache if your component suspends during the initial mount. In the future, React may add more features that take advantage of throwing away the cache--for example, if React adds built-in support for virtualized lists in the future, it would make sense to throw away the cache for items that scroll out of the virtualized table viewport. This should be fine if you rely on `useMemo` solely as a performance optimization. Otherwise, a [state variable](/reference/react/useState#avoiding-recreating-the-initial-state) or a [ref](/reference/react/useRef#avoiding-recreating-the-ref-contents) may be more appropriate. +* `useMemo` é um Hook, então você só pode chamá-lo **no nível superior do seu componente** ou dos seus próprios Hooks. Você não pode chamá-lo dentro de loops ou condições. Se você precisar disso, extraia um novo componente e mova o state para ele. +* Em Strict Mode, o React **chamará sua função de cálculo duas vezes** para [ajudá-lo a encontrar impurezas acidentais.](#my-calculation-runs-twice-on-every-re-render) Este é um comportamento apenas de desenvolvimento e não afeta a produção. Se sua função de cálculo for pura (como deveria ser), isso não deve afetar sua lógica. O resultado de uma das chamadas será ignorado. +* O React **não vai descartar o valor armazenado em cache, a menos que haja um motivo específico para isso.** Por exemplo, em desenvolvimento, o React descarta o cache quando você edita o arquivo do seu componente. Tanto em desenvolvimento quanto em produção, o React descartará o cache se seu componente suspender durante a montagem inicial. No futuro, o React pode adicionar mais recursos que se beneficiam de descartar o cache - por exemplo, se o React adicionar suporte embutido para listas virtualizadas no futuro, faria sentido descartar o cache para itens que saem da janela de visualização da tabela virtualizada. Isso deve ser bom se você confiar no `useMemo` apenas como uma otimização de desempenho. Caso contrário, uma [variável de state](/reference/react/useState#avoiding-recreating-the-initial-state) ou uma [ref](/reference/react/useRef#avoiding-recreating-the-ref-contents) pode ser mais apropriada. -Caching return values like this is also known as [*memoization*,](https://en.wikipedia.org/wiki/Memoization) which is why this Hook is called `useMemo`. +Armazenar em cache valores de retorno como este também é conhecido como [*memoization*,](https://pt.wikipedia.org/wiki/Memoiza%C3%A7%C3%A3o) e é por isso que este Hook é chamado `useMemo`. --- -## Usage {/*usage*/} +## Uso {/*usage*/} -### Skipping expensive recalculations {/*skipping-expensive-recalculations*/} +### Ignorando cálculos caros {/*skipping-expensive-recalculations*/} -To cache a calculation between re-renders, wrap it in a `useMemo` call at the top level of your component: +Para armazenar em cache um cálculo entre as renderizações, envolva-o em uma chamada `useMemo` no nível superior do seu componente: ```js [[3, 4, "visibleTodos"], [1, 4, "() => filterTodos(todos, tab)"], [2, 4, "[todos, tab]"]] import { useMemo } from 'react'; @@ -77,20 +77,20 @@ function TodoList({ todos, tab, theme }) { } ``` -You need to pass two things to `useMemo`: +Você precisa passar duas coisas para `useMemo`: -1. A calculation function that takes no arguments, like `() =>`, and returns what you wanted to calculate. -2. A list of dependencies including every value within your component that's used inside your calculation. +1. Uma função de cálculo que não recebe argumentos, como `() =>`, e retorna o que você queria calcular. +2. Uma lista de dependências incluindo cada valor dentro do seu componente que é usado dentro do seu cálculo. -On the initial render, the value you'll get from `useMemo` will be the result of calling your calculation. +Na renderização inicial, o valor que você obterá de `useMemo` será o resultado da chamada da sua cálculo. -On every subsequent render, React will compare the dependencies with the dependencies you passed during the last render. If none of the dependencies have changed (compared with [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)), `useMemo` will return the value you already calculated before. Otherwise, React will re-run your calculation and return the new value. +Em cada renderização subsequente, o React comparará as dependências com as dependências que você passou durante a última renderização. Se nenhuma das dependências tiver mudado (comparada com [`Object.is`](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/is)), `useMemo` retornará o valor que você já calculou antes. Caso contrário, o React irá executar seu cálculo e retornar o novo valor. -In other words, `useMemo` caches a calculation result between re-renders until its dependencies change. +Em outras palavras, `useMemo` armazena em cache um resultado de cálculo entre as renderizações até que suas dependências mudem. -**Let's walk through an example to see when this is useful.** +**Vamos analisar um exemplo para ver quando isso é útil.** -By default, React will re-run the entire body of your component every time that it re-renders. For example, if this `TodoList` updates its state or receives new props from its parent, the `filterTodos` function will re-run: +Por padrão, o React irá executar todo o corpo do seu componente toda vez que ele renderizar novamente. Por exemplo, se este `TodoList` atualizar seu state ou receber novas props de seu pai, a função `filterTodos` será executada novamente: ```js {2} function TodoList({ todos, tab, theme }) { @@ -99,21 +99,21 @@ function TodoList({ todos, tab, theme }) { } ``` -Usually, this isn't a problem because most calculations are very fast. However, if you're filtering or transforming a large array, or doing some expensive computation, you might want to skip doing it again if data hasn't changed. If both `todos` and `tab` are the same as they were during the last render, wrapping the calculation in `useMemo` like earlier lets you reuse `visibleTodos` you've already calculated before. +Normalmente, isso não é um problema porque a maioria dos cálculos é muito rápida. No entanto, se você estiver filtrando ou transformando uma array grande ou fazendo alguma computação cara, talvez você queira pular fazê-lo novamente se os dados não tiverem mudado. Se ambos `todos` e `tab` forem os mesmos do que eram durante a última renderização, envolver o cálculo em `useMemo` como antes permite que você reutilize `visibleTodos` que você já calculou antes. -This type of caching is called *[memoization.](https://en.wikipedia.org/wiki/Memoization)* +Este tipo de armazenamento em cache é chamado de *[memoization](https://pt.wikipedia.org/wiki/Memoiza%C3%A7%C3%A3o)*. -**You should only rely on `useMemo` as a performance optimization.** If your code doesn't work without it, find the underlying problem and fix it first. Then you may add `useMemo` to improve performance. +**Você só deve confiar em `useMemo` como uma otimização de desempenho.** Se seu código não funcionar sem ele, encontre o problema subjacente e corrija-o primeiro. Então você pode adicionar `useMemo` para melhorar o desempenho. -#### How to tell if a calculation is expensive? {/*how-to-tell-if-a-calculation-is-expensive*/} +#### Como saber se um cálculo é caro? {/*how-to-tell-if-a-calculation-is-expensive*/} -In general, unless you're creating or looping over thousands of objects, it's probably not expensive. If you want to get more confidence, you can add a console log to measure the time spent in a piece of code: +Em geral, a menos que você esteja criando ou percorrendo milhares de objetos, provavelmente não é caro. Se você quiser ter mais confiança, pode adicionar um console log para medir o tempo gasto em um trecho de código: ```js {1,3} console.time('filter array'); @@ -121,59 +121,59 @@ const visibleTodos = filterTodos(todos, tab); console.timeEnd('filter array'); ``` -Perform the interaction you're measuring (for example, typing into the input). You will then see logs like `filter array: 0.15ms` in your console. If the overall logged time adds up to a significant amount (say, `1ms` or more), it might make sense to memoize that calculation. As an experiment, you can then wrap the calculation in `useMemo` to verify whether the total logged time has decreased for that interaction or not: +Execute a interação que você está medindo (por exemplo, digitar na entrada). Você verá logs como `filter array: 0.15ms` no seu console. Se o tempo total registrado somar uma quantidade significativa (digamos, `1ms` ou mais), pode fazer sentido memorizar esse cálculo. Como um experimento, você pode então envolver o cálculo em `useMemo` para verificar se o tempo total registrado diminuiu para aquela interação ou não: ```js console.time('filter array'); const visibleTodos = useMemo(() => { - return filterTodos(todos, tab); // Skipped if todos and tab haven't changed + return filterTodos(todos, tab); // Ignorado se todos e tab não mudaram }, [todos, tab]); console.timeEnd('filter array'); ``` -`useMemo` won't make the *first* render faster. It only helps you skip unnecessary work on updates. +`useMemo` não vai tornar a *primeira* renderização mais rápida. Ele só ajuda você a pular trabalho desnecessário em atualizações. -Keep in mind that your machine is probably faster than your users' so it's a good idea to test the performance with an artificial slowdown. For example, Chrome offers a [CPU Throttling](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) option for this. +Tenha em mente que sua máquina provavelmente é mais rápida do que a de seus usuários, então é uma boa ideia testar o desempenho com uma lentidão artificial. Por exemplo, o Chrome oferece uma opção de [CPU Throttling](https://developer.chrome.com/blog/new-in-devtools-61/#throttling) para isso. -Also note that measuring performance in development will not give you the most accurate results. (For example, when [Strict Mode](/reference/react/StrictMode) is on, you will see each component render twice rather than once.) To get the most accurate timings, build your app for production and test it on a device like your users have. +Observe também que medir o desempenho no desenvolvimento não fornecerá os resultados mais precisos. (Por exemplo, quando o [Strict Mode](/reference/react/StrictMode) estiver ativado, você verá cada componente renderizar duas vezes em vez de uma.) Para obter os tempos mais precisos, crie seu aplicativo para produção e teste-o em um dispositivo como seus usuários têm. -#### Should you add useMemo everywhere? {/*should-you-add-usememo-everywhere*/} +#### Você deve adicionar useMemo em todos os lugares? {/*should-you-add-usememo-everywhere*/} -If your app is like this site, and most interactions are coarse (like replacing a page or an entire section), memoization is usually unnecessary. On the other hand, if your app is more like a drawing editor, and most interactions are granular (like moving shapes), then you might find memoization very helpful. +Se seu app for como este site e a maioria das interações for grosseira (como substituir uma página ou uma seção inteira), a memoization geralmente é desnecessária. Por outro lado, se seu app for mais parecido com um editor de desenho e a maioria das interações for granular (como mover formas), você pode achar a memoization muito útil. -Optimizing with `useMemo` is only valuable in a few cases: +Otimizar com `useMemo` só é valioso em alguns casos: -- The calculation you're putting in `useMemo` is noticeably slow, and its dependencies rarely change. -- You pass it as a prop to a component wrapped in [`memo`.](/reference/react/memo) You want to skip re-rendering if the value hasn't changed. Memoization lets your component re-render only when dependencies aren't the same. -- The value you're passing is later used as a dependency of some Hook. For example, maybe another `useMemo` calculation value depends on it. Or maybe you are depending on this value from [`useEffect.`](/reference/react/useEffect) +* O cálculo que você está colocando em `useMemo` é notavelmente lento e suas dependências raramente mudam. +* Você o passa como uma prop para um componente encapsulado em [`memo`.](/reference/react/memo) Você quer pular a re-renderização se o valor não tiver mudado. A memoization permite que seu componente renderize novamente apenas quando as dependências não são as mesmas. +* O valor que você está passando é posteriormente usado como uma dependência de algum Hook. Por exemplo, talvez outro valor de cálculo `useMemo` dependa dele. Ou talvez você esteja dependendo desse valor de [`useEffect.`](/reference/react/useEffect) -There is no benefit to wrapping a calculation in `useMemo` in other cases. There is no significant harm to doing that either, so some teams choose to not think about individual cases, and memoize as much as possible. The downside of this approach is that code becomes less readable. Also, not all memoization is effective: a single value that's "always new" is enough to break memoization for an entire component. +Não há nenhum benefício em encapsular um cálculo em `useMemo` em outros casos. Também não há nenhum dano significativo em fazer isso, então algumas equipes optam por não pensar em casos individuais e memorizar o máximo possível. A desvantagem dessa abordagem é que o código se torna menos legível. Além disso, nem toda memoization é eficaz: um único valor que é "sempre novo" é suficiente para quebrar a memoization para um componente inteiro. -**In practice, you can make a lot of memoization unnecessary by following a few principles:** +**Na prática, você pode tornar muita memoization desnecessária seguindo alguns princípios:** -1. When a component visually wraps other components, let it [accept JSX as children.](/learn/passing-props-to-a-component#passing-jsx-as-children) This way, when the wrapper component updates its own state, React knows that its children don't need to re-render. -1. Prefer local state and don't [lift state up](/learn/sharing-state-between-components) any further than necessary. For example, don't keep transient state like forms and whether an item is hovered at the top of your tree or in a global state library. -1. Keep your [rendering logic pure.](/learn/keeping-components-pure) If re-rendering a component causes a problem or produces some noticeable visual artifact, it's a bug in your component! Fix the bug instead of adding memoization. -1. Avoid [unnecessary Effects that update state.](/learn/you-might-not-need-an-effect) Most performance problems in React apps are caused by chains of updates originating from Effects that cause your components to render over and over. -1. Try to [remove unnecessary dependencies from your Effects.](/learn/removing-effect-dependencies) For example, instead of memoization, it's often simpler to move some object or a function inside an Effect or outside the component. +1. Quando um componente envolve visualmente outros componentes, deixe-o [aceitar JSX como filhos.](/learn/passing-props-to-a-component#passing-jsx-as-children) Dessa forma, quando o componente wrapper atualiza seu próprio state, o React sabe que seus filhos não precisam renderizar novamente. +2. Prefira o state local e não [eleve o state](/learn/sharing-state-between-components) mais do que o necessário. Por exemplo, não mantenha o state transitório, como formulários e se um item está em hover, no topo da sua árvore ou em uma biblioteca de state global. +3. Mantenha sua [lógica de renderização pura.](/learn/keeping-components-pure) Se renderizar novamente um componente causar um problema ou produzir algum artefato visual perceptível, é um erro no seu componente! Corrija o erro em vez de adicionar memoization. +4. Evite [Effects desnecessários que atualizam o state.](/learn/you-might-not-need-an-effect) A maioria dos problemas de desempenho em aplicativos React é causada por cadeias de atualizações originadas de Effects que fazem seus componentes renderizarem repetidamente. +5. Tente [remover dependências desnecessárias de seus Effects.](/learn/removing-effect-dependencies) Por exemplo, em vez de memoization, muitas vezes é mais simples mover algum objeto ou uma função dentro de um Effect ou fora do componente. -If a specific interaction still feels laggy, [use the React Developer Tools profiler](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html) to see which components would benefit the most from memoization, and add memoization where needed. These principles make your components easier to debug and understand, so it's good to follow them in any case. In the long term, we're researching [doing granular memoization automatically](https://www.youtube.com/watch?v=lGEMwh32soc) to solve this once and for all. +Se uma interação específica ainda parecer lenta, [use o React Developer Tools profiler](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html) para ver quais componentes se beneficiariam mais da memoization e adicione memoization onde for necessário. Esses princípios tornam seus componentes mais fáceis de depurar e entender, por isso é bom segui-los em qualquer caso. A longo prazo, estamos pesquisando [fazer memoization granularmente automaticamente](https://www.youtube.com/watch?v=lGEMwh32soc) para resolver isso de uma vez por todas. - + -#### Skipping recalculation with `useMemo` {/*skipping-recalculation-with-usememo*/} +#### Ignorando o recálculo com `useMemo` {/*skipping-recalculation-with-usememo*/} -In this example, the `filterTodos` implementation is **artificially slowed down** so that you can see what happens when some JavaScript function you're calling during rendering is genuinely slow. Try switching the tabs and toggling the theme. +Neste exemplo, a implementação `filterTodos` é **artificialmente retardada** para que você possa ver o que acontece quando alguma função JavaScript que você está chamando durante a renderização é genuinamente lenta. Tente alternar as guias e alternar o tema. -Switching the tabs feels slow because it forces the slowed down `filterTodos` to re-execute. That's expected because the `tab` has changed, and so the entire calculation *needs* to re-run. (If you're curious why it runs twice, it's explained [here.](#my-calculation-runs-twice-on-every-re-render)) +Alternar as guias parece lento porque força o `filterTodos` desacelerado a ser reexecutado. Isso é esperado porque a `tab` mudou e, portanto, todo o cálculo *precisa* ser executado novamente. (Se você está curioso por que ele é executado duas vezes, é explicado [aqui.](#my-calculation-runs-twice-on-every-re-render)) -Toggle the theme. **Thanks to `useMemo`, it's fast despite the artificial slowdown!** The slow `filterTodos` call was skipped because both `todos` and `tab` (which you pass as dependencies to `useMemo`) haven't changed since the last render. +Alterne o tema. **Graças ao `useMemo`, ele é rápido apesar da lentidão artificial!** A chamada `filterTodos` lenta foi ignorada porque tanto `todos` quanto `tab` (que você passa como dependências para `useMemo`) não mudaram desde a última renderização. @@ -299,11 +299,11 @@ label { -#### Always recalculating a value {/*always-recalculating-a-value*/} +#### Sempre recalculando um valor {/*always-recalculating-a-value*/} -In this example, the `filterTodos` implementation is also **artificially slowed down** so that you can see what happens when some JavaScript function you're calling during rendering is genuinely slow. Try switching the tabs and toggling the theme. +Neste exemplo, a implementação `filterTodos` também está **artificialmente desacelerada** para que você possa ver o que acontece quando alguma função JavaScript que você está chamando durante a renderização é genuinamente lenta. Tente alternar as guias e alternar o tema. -Unlike in the previous example, toggling the theme is also slow now! This is because **there is no `useMemo` call in this version,** so the artificially slowed down `filterTodos` gets called on every re-render. It is called even if only `theme` has changed. +Ao contrário do exemplo anterior, alternar o tema também é lento agora! Isso ocorre porque **não há nenhuma chamada `useMemo` nesta versão,** então o `filterTodos` artificialmente desacelerado é chamado em cada nova renderização. Ele é chamado mesmo que apenas o `theme` tenha mudado. @@ -423,7 +423,7 @@ label { -However, here is the same code **with the artificial slowdown removed.** Does the lack of `useMemo` feel noticeable or not? +No entanto, aqui está o mesmo código **com a desaceleração artificial removida.** A ausência de `useMemo` parece perceptível ou não? @@ -538,9 +538,9 @@ label { -Quite often, code without memoization works fine. If your interactions are fast enough, you might not need memoization. +Muitas vezes, o código sem memoization funciona bem. Se suas interações forem rápidas o suficiente, talvez você não precise de memoization. -You can try increasing the number of todo items in `utils.js` and see how the behavior changes. This particular calculation wasn't very expensive to begin with, but if the number of todos grows significantly, most of the overhead will be in re-rendering rather than in the filtering. Keep reading below to see how you can optimize re-rendering with `useMemo`. +Você pode tentar aumentar o número de itens de tarefas em `utils.js` e ver como o comportamento muda. Este cálculo em particular não era muito caro para começar, mas se o número de tarefas crescer significativamente, a maior parte da sobrecarga estará na nova renderização em vez da filtragem. Continue lendo abaixo para ver como você pode otimizar a nova renderização com `useMemo`. @@ -548,9 +548,9 @@ You can try increasing the number of todo items in `utils.js` and see how the be --- -### Skipping re-rendering of components {/*skipping-re-rendering-of-components*/} +### Ignorando a nova renderização de componentes {/*skipping-re-rendering-of-components*/} -In some cases, `useMemo` can also help you optimize performance of re-rendering child components. To illustrate this, let's say this `TodoList` component passes the `visibleTodos` as a prop to the child `List` component: +Em alguns casos, `useMemo` também pode ajudá-lo a otimizar o desempenho da nova renderização de componentes filhos. Para ilustrar isso, digamos que este componente `TodoList` passe o `visibleTodos` como uma prop para o componente filho `List`: ```js {5} export default function TodoList({ todos, tab, theme }) { @@ -563,9 +563,9 @@ export default function TodoList({ todos, tab, theme }) { } ``` -You've noticed that toggling the `theme` prop freezes the app for a moment, but if you remove `` from your JSX, it feels fast. This tells you that it's worth trying to optimize the `List` component. +Você notou que alternar a prop `theme` trava o aplicativo por um momento, mas se você remover `` do seu JSX, ele parece rápido. Isso indica que vale a pena tentar otimizar o componente `List`. -**By default, when a component re-renders, React re-renders all of its children recursively.** This is why, when `TodoList` re-renders with a different `theme`, the `List` component *also* re-renders. This is fine for components that don't require much calculation to re-render. But if you've verified that a re-render is slow, you can tell `List` to skip re-rendering when its props are the same as on last render by wrapping it in [`memo`:](/reference/react/memo) +**Por padrão, quando um componente renderiza novamente, o React renderiza novamente todos os seus filhos recursivamente.** É por isso que, quando `TodoList` renderiza novamente com um `theme` diferente, o componente `List` *também* renderiza novamente. Isso é bom para componentes que não exigem muito cálculo para renderizar novamente. Mas se você verificou que uma nova renderização é lenta, pode dizer ao `List` para pular a nova renderização quando suas props forem as mesmas da última renderização, envolvendo-o em [`memo`:](/reference/react/memo) ```js {3,5} import { memo } from 'react'; @@ -575,47 +575,46 @@ const List = memo(function List({ items }) { }); ``` -**With this change, `List` will skip re-rendering if all of its props are the *same* as on the last render.** This is where caching the calculation becomes important! Imagine that you calculated `visibleTodos` without `useMemo`: +**Com essa alteração, `List` pulará a nova renderização se todas as suas props forem *iguais* às da última renderização.** É aqui que o armazenamento em cache do cálculo se torna importante! Imagine que você calculou `visibleTodos` sem `useMemo`: ```js {2-3,6-7} export default function TodoList({ todos, tab, theme }) { - // Every time the theme changes, this will be a different array... + // Sempre que o tema muda, esta será uma array diferente... const visibleTodos = filterTodos(todos, tab); return (
- {/* ... so List's props will never be the same, and it will re-render every time */} + {/* ...então as props do List nunca serão as mesmas e ele irá renderizar novamente toda vez */}
); } ``` -**In the above example, the `filterTodos` function always creates a *different* array,** similar to how the `{}` object literal always creates a new object. Normally, this wouldn't be a problem, but it means that `List` props will never be the same, and your [`memo`](/reference/react/memo) optimization won't work. This is where `useMemo` comes in handy: +**No exemplo acima, a função `filterTodos` sempre cria uma array *diferente*,** semelhante à forma como o literal de objeto `{}` sempre cria um novo objeto. Normalmente, isso não seria um problema, mas significa que as props de `List` nunca serão as mesmas, e sua otimização [`memo`](/reference/react/memo) não funcionará. É aqui que `useMemo` é útil: ```js {2-3,5,9-10} export default function TodoList({ todos, tab, theme }) { - // Tell React to cache your calculation between re-renders... + // Diga ao React para armazenar em cache seu cálculo entre novas renderizações... const visibleTodos = useMemo( () => filterTodos(todos, tab), - [todos, tab] // ...so as long as these dependencies don't change... + [todos, tab] // ...para que, desde que essas dependências não mudem... ); return (
- {/* ...List will receive the same props and can skip re-rendering */} + {/* ...List receberá as mesmas props e poderá pular a nova renderização */}
); } ``` - -**By wrapping the `visibleTodos` calculation in `useMemo`, you ensure that it has the *same* value between the re-renders** (until dependencies change). You don't *have to* wrap a calculation in `useMemo` unless you do it for some specific reason. In this example, the reason is that you pass it to a component wrapped in [`memo`,](/reference/react/memo) and this lets it skip re-rendering. There are a few other reasons to add `useMemo` which are described further on this page. +**Ao encapsular o cálculo `visibleTodos` em `useMemo`, você garante que ele tenha o *mesmo* valor entre as novas renderizações** (até que as dependências mudem). Você não *precisa* encapsular um cálculo em `useMemo`, a menos que o faça por algum motivo específico. Neste exemplo, a razão é que você o passa para um componente encapsulado em [`memo`,](/reference/react/memo) e isso permite que ele pule a nova renderização. Existem algumas outras razões para adicionar `useMemo`, que são descritas mais adiante nesta página. -#### Memoizing individual JSX nodes {/*memoizing-individual-jsx-nodes*/} +#### Memorizando nós JSX individuais {/*memoizing-individual-jsx-nodes*/} -Instead of wrapping `List` in [`memo`](/reference/react/memo), you could wrap the `` JSX node itself in `useMemo`: +Em vez de encapsular `List` em [`memo`](/reference/react/memo), você pode encapsular o próprio nó JSX `` em `useMemo`: ```js {3,6} export default function TodoList({ todos, tab, theme }) { @@ -628,26 +627,26 @@ export default function TodoList({ todos, tab, theme }) { ); } ``` +``` +O comportamento seria o mesmo. Se os `visibleTodos` não mudaram, `List` não será renderizado novamente. -The behavior would be the same. If the `visibleTodos` haven't changed, `List` won't be re-rendered. - -A JSX node like `` is an object like `{ type: List, props: { items: visibleTodos } }`. Creating this object is very cheap, but React doesn't know whether its contents is the same as last time or not. This is why by default, React will re-render the `List` component. +Um nó JSX como `` é um objeto como `{ type: List, props: { items: visibleTodos } }`. Criar este objeto é muito barato, mas o React não sabe se seu conteúdo é o mesmo da última vez ou não. É por isso que, por padrão, o React irá renderizar novamente o componente `List`. -However, if React sees the same exact JSX as during the previous render, it won't try to re-render your component. This is because JSX nodes are [immutable.](https://en.wikipedia.org/wiki/Immutable_object) A JSX node object could not have changed over time, so React knows it's safe to skip a re-render. However, for this to work, the node has to *actually be the same object*, not merely look the same in code. This is what `useMemo` does in this example. +No entanto, se o React vê o mesmo JSX exato que durante a renderização anterior, ele não tentará renderizar seu componente novamente. Isso ocorre porque os nós JSX são [imutáveis.](https://pt.wikipedia.org/wiki/Objeto_imutável) Um objeto de nó JSX não poderia ter mudado com o tempo, então o React sabe que é seguro pular uma nova renderização. No entanto, para que isso funcione, o nó tem que *realmente ser o mesmo objeto*, não apenas ter a mesma aparência no código. É isso que o `useMemo` faz neste exemplo. -Manually wrapping JSX nodes into `useMemo` is not convenient. For example, you can't do this conditionally. This is usually why you would wrap components with [`memo`](/reference/react/memo) instead of wrapping JSX nodes. +Envolver manualmente nós JSX em `useMemo` não é conveniente. Por exemplo, você não pode fazer isso condicionalmente. É por isso que geralmente você envolveria componentes com [`memo`](/reference/react/memo) em vez de envolver nós JSX. - + -#### Skipping re-rendering with `useMemo` and `memo` {/*skipping-re-rendering-with-usememo-and-memo*/} +#### Pular a renderização novamente com `useMemo` e `memo` {/*skipping-re-rendering-with-usememo-and-memo*/} -In this example, the `List` component is **artificially slowed down** so that you can see what happens when a React component you're rendering is genuinely slow. Try switching the tabs and toggling the theme. +Neste exemplo, o componente `List` é **artificialmente atrasado** para que você possa ver o que acontece quando um componente React que você está renderizando é realmente lento. Tente alternar as abas e alternar o tema. -Switching the tabs feels slow because it forces the slowed down `List` to re-render. That's expected because the `tab` has changed, and so you need to reflect the user's new choice on the screen. +Alternar as abas parece lento porque força o `List` atrasado a renderizar novamente. Isso é esperado porque a `tab` mudou e, portanto, você precisa refletir a nova escolha do usuário na tela. -Next, try toggling the theme. **Thanks to `useMemo` together with [`memo`](/reference/react/memo), it’s fast despite the artificial slowdown!** The `List` skipped re-rendering because the `visibleTodos` array has not changed since the last render. The `visibleTodos` array has not changed because both `todos` and `tab` (which you pass as dependencies to `useMemo`) haven't changed since the last render. +Em seguida, tente alternar o tema. **Graças ao `useMemo` em conjunto com [`memo`](/reference/react/memo), é rápido, apesar da lentidão artificial!** O `List` pulou a renderização novamente porque o array `visibleTodos` não foi alterado desde a última renderização. O array `visibleTodos` não foi alterado porque tanto `todos` quanto `tab` (que você passa como dependências para `useMemo`) não foram alterados desde a última renderização. @@ -785,11 +784,11 @@ label { -#### Always re-rendering a component {/*always-re-rendering-a-component*/} +#### Sempre renderizando novamente um componente {/*always-re-rendering-a-component*/} -In this example, the `List` implementation is also **artificially slowed down** so that you can see what happens when some React component you're rendering is genuinely slow. Try switching the tabs and toggling the theme. +Neste exemplo, a implementação do `List` também é **artificialmente atrasada** para que você possa ver o que acontece quando algum componente React que você está renderizando é realmente lento. Tente alternar as abas e alternar o tema. -Unlike in the previous example, toggling the theme is also slow now! This is because **there is no `useMemo` call in this version,** so the `visibleTodos` is always a different array, and the slowed down `List` component can't skip re-rendering. +Ao contrário do exemplo anterior, alternar o tema também está lento agora! Isso ocorre porque **não há nenhuma chamada `useMemo` nesta versão,** então o `visibleTodos` é sempre um array diferente, e o componente `List` com lentidão não pode pular a renderização novamente. @@ -921,7 +920,7 @@ label { -However, here is the same code **with the artificial slowdown removed.** Does the lack of `useMemo` feel noticeable or not? +No entanto, aqui está o mesmo código **com a lentidão artificial removida.** A ausência de `useMemo` parece perceptível ou não? @@ -1046,9 +1045,9 @@ label { -Quite often, code without memoization works fine. If your interactions are fast enough, you don't need memoization. +Muitas vezes, o código sem memoização funciona bem. Se suas interações forem rápidas o suficiente, você não precisa de memoização. -Keep in mind that you need to run React in production mode, disable [React Developer Tools](/learn/react-developer-tools), and use devices similar to the ones your app's users have in order to get a realistic sense of what's actually slowing down your app. +Tenha em mente que você precisa executar o React no modo de produção, desativar as [Ferramentas de Desenvolvedor React](/learn/react-developer-tools) e usar dispositivos semelhantes aos que os usuários do seu aplicativo têm para obter uma noção realista do que realmente está deixando seu aplicativo lento. @@ -1056,9 +1055,9 @@ Keep in mind that you need to run React in production mode, disable [React Devel --- -### Preventing an Effect from firing too often {/*preventing-an-effect-from-firing-too-often*/} +### Impedindo que um Effect dispare com muita frequência {/*preventing-an-effect-from-firing-too-often*/} -Sometimes, you might want to use a value inside an [Effect:](/learn/synchronizing-with-effects) +Às vezes, você pode querer usar um valor dentro de um [Effect:](/learn/synchronizing-with-effects) ```js {4-7,10} function ChatRoom({ roomId }) { @@ -1075,8 +1074,7 @@ function ChatRoom({ roomId }) { // ... ``` -This creates a problem. [Every reactive value must be declared as a dependency of your Effect.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) However, if you declare `options` as a dependency, it will cause your Effect to constantly reconnect to the chat room: - +Isso cria um problema. [Cada valor reativo deve ser declarado como uma dependência do seu Effect.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) No entanto, se você declarar `options` como dependência, isso fará com que seu Effect se reconecte constantemente ao chat room: ```js {5} useEffect(() => { @@ -1087,7 +1085,7 @@ This creates a problem. [Every reactive value must be declared as a dependency o // ... ``` -To solve this, you can wrap the object you need to call from an Effect in `useMemo`: +Para resolver isso, você pode envolver o objeto que você precisa chamar de um Effect em `useMemo`: ```js {4-9,16} function ChatRoom({ roomId }) { @@ -1108,9 +1106,9 @@ function ChatRoom({ roomId }) { // ... ``` -This ensures that the `options` object is the same between re-renders if `useMemo` returns the cached object. +Isso garante que o objeto `options` seja o mesmo entre as novas renderizações se `useMemo` retornar o objeto em cache. -However, since `useMemo` is performance optimization, not a semantic guarantee, React may throw away the cached value if [there is a specific reason to do that](#caveats). This will also cause the effect to re-fire, **so it's even better to remove the need for a function dependency** by moving your object *inside* the Effect: +No entanto, como `useMemo` é uma otimização de desempenho, não uma garantia semântica, o React pode descartar o valor armazenado em cache se [houver uma razão específica para fazê-lo](#caveats). Isso também fará com que o efeito seja disparado novamente, **portanto, é ainda melhor remover a necessidade de uma dependência de função** movendo seu objeto *dentro* do Effect: ```js {5-8,13} function ChatRoom({ roomId }) { @@ -1129,12 +1127,11 @@ function ChatRoom({ roomId }) { // ... ``` -Now your code is simpler and doesn't need `useMemo`. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect) +Agora seu código é mais simples e não precisa de `useMemo`. [Saiba mais sobre como remover dependências de Effect.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect) +### Memoizando uma dependência de outro Hook {/*memoizing-a-dependency-of-another-hook*/} -### Memoizing a dependency of another Hook {/*memoizing-a-dependency-of-another-hook*/} - -Suppose you have a calculation that depends on an object created directly in the component body: +Suponha que você tenha um cálculo que dependa de um objeto criado diretamente no corpo do componente: ```js {2} function Dropdown({ allItems, text }) { @@ -1146,9 +1143,9 @@ function Dropdown({ allItems, text }) { // ... ``` -Depending on an object like this defeats the point of memoization. When a component re-renders, all of the code directly inside the component body runs again. **The lines of code creating the `searchOptions` object will also run on every re-render.** Since `searchOptions` is a dependency of your `useMemo` call, and it's different every time, React knows the dependencies are different, and recalculate `searchItems` every time. +Depender de um objeto como esse anula a utilidade da memoização. Quando um componente renderiza novamente, todo o código diretamente dentro do corpo do componente é executado novamente. **As linhas de código que criam o objeto `searchOptions` também serão executadas em cada nova renderização.** Como `searchOptions` é uma dependência da sua chamada `useMemo` e é diferente toda vez, o React sabe que as dependências são diferentes e recalcula `searchItems` toda vez. -To fix this, you could memoize the `searchOptions` object *itself* before passing it as a dependency: +Para corrigir isso, você pode memoizar o próprio objeto `searchOptions` antes de passá-lo como dependência: ```js {2-4} function Dropdown({ allItems, text }) { @@ -1162,7 +1159,7 @@ function Dropdown({ allItems, text }) { // ... ``` -In the example above, if the `text` did not change, the `searchOptions` object also won't change. However, an even better fix is to move the `searchOptions` object declaration *inside* of the `useMemo` calculation function: +No exemplo acima, se o `text` não mudar, o objeto `searchOptions` também não mudará. No entanto, uma correção ainda melhor é mover a declaração do objeto `searchOptions` *dentro* da função de cálculo `useMemo`: ```js {3} function Dropdown({ allItems, text }) { @@ -1173,13 +1170,13 @@ function Dropdown({ allItems, text }) { // ... ``` -Now your calculation depends on `text` directly (which is a string and can't "accidentally" become different). +Agora seu cálculo depende diretamente de `text` (que é uma string e não pode "acidentalmente" se tornar diferente). --- -### Memoizing a function {/*memoizing-a-function*/} +### Memoizando uma função {/*memoizing-a-function*/} -Suppose the `Form` component is wrapped in [`memo`.](/reference/react/memo) You want to pass a function to it as a prop: +Suponha que o componente `Form` esteja envolvido em [`memo`.](/reference/react/memo) Você quer passar uma função para ele como uma prop: ```js {2-7} export default function ProductPage({ productId, referrer }) { @@ -1194,9 +1191,9 @@ export default function ProductPage({ productId, referrer }) { } ``` -Just as `{}` creates a different object, function declarations like `function() {}` and expressions like `() => {}` produce a *different* function on every re-render. By itself, creating a new function is not a problem. This is not something to avoid! However, if the `Form` component is memoized, presumably you want to skip re-rendering it when no props have changed. A prop that is *always* different would defeat the point of memoization. +Assim como `{}` cria um objeto diferente, declarações de função como `function() {}` e expressões como `() => {}` produzem uma função *diferente* em cada nova renderização. Sozinho, criar uma nova função não é um problema. Isso não é algo a ser evitado! No entanto, se o componente `Form` for memoizado, presume-se que você deseja pular a renderização dele quando nenhuma prop foi alterada. Uma prop que é *sempre* diferente frustraria o propósito da memoização. -To memoize a function with `useMemo`, your calculation function would have to return another function: +Para memoizar uma função com `useMemo`, sua função de cálculo teria que retornar outra função: ```js {2-3,8-9} export default function Page({ productId, referrer }) { @@ -1213,7 +1210,7 @@ export default function Page({ productId, referrer }) { } ``` -This looks clunky! **Memoizing functions is common enough that React has a built-in Hook specifically for that. Wrap your functions into [`useCallback`](/reference/react/useCallback) instead of `useMemo`** to avoid having to write an extra nested function: +Isso parece desajeitado! **Memoizar funções é comum o suficiente que o React possui um Hook embutido especificamente para isso. Envolva suas funções em [`useCallback`](/reference/react/useCallback) em vez de `useMemo`** para evitar ter que escrever uma função aninhada extra: ```js {2,7} export default function Page({ productId, referrer }) { @@ -1228,88 +1225,88 @@ export default function Page({ productId, referrer }) { } ``` -The two examples above are completely equivalent. The only benefit to `useCallback` is that it lets you avoid writing an extra nested function inside. It doesn't do anything else. [Read more about `useCallback`.](/reference/react/useCallback) +Os dois exemplos acima são completamente equivalentes. A única vantagem do `useCallback` é que ele permite que você evite escrever uma função aninhada extra por dentro. Ele não faz mais nada. [Leia mais sobre `useCallback`.](/reference/react/useCallback) --- -## Troubleshooting {/*troubleshooting*/} +## Solução de problemas {/*troubleshooting*/} -### My calculation runs twice on every re-render {/*my-calculation-runs-twice-on-every-re-render*/} +### Meu cálculo é executado duas vezes em cada nova renderização {/*my-calculation-runs-twice-on-every-re-render*/} -In [Strict Mode](/reference/react/StrictMode), React will call some of your functions twice instead of once: +No [Strict Mode](/reference/react/StrictMode), o React chamará algumas de suas funções duas vezes em vez de uma: ```js {2,5,6} function TodoList({ todos, tab }) { - // This component function will run twice for every render. + // Esta função componente será executada duas vezes para cada renderização. const visibleTodos = useMemo(() => { - // This calculation will run twice if any of the dependencies change. + // Este cálculo será executado duas vezes se alguma das dependências mudar. return filterTodos(todos, tab); }, [todos, tab]); // ... ``` -This is expected and shouldn't break your code. +Isso é esperado e não deve quebrar seu código. -This **development-only** behavior helps you [keep components pure.](/learn/keeping-components-pure) React uses the result of one of the calls, and ignores the result of the other call. As long as your component and calculation functions are pure, this shouldn't affect your logic. However, if they are accidentally impure, this helps you notice and fix the mistake. +Este comportamento **apenas para desenvolvimento** ajuda você a [manter os componentes puros.](/learn/keeping-components-pure) O React usa o resultado de uma das chamadas e ignora o resultado da outra chamada. Contanto que seu componente e as funções de cálculo sejam puros, isso não deve afetar sua lógica. No entanto, se eles forem acidentalmente impuros, isso o ajudará a notar e corrigir o erro. -For example, this impure calculation function mutates an array you received as a prop: +Por exemplo, esta função de cálculo impura muta uma array que você recebeu como prop: ```js {2-3} const visibleTodos = useMemo(() => { - // 🚩 Mistake: mutating a prop + // 🚩 Erro: mutando uma prop todos.push({ id: 'last', text: 'Go for a walk!' }); const filtered = filterTodos(todos, tab); return filtered; }, [todos, tab]); ``` -React calls your function twice, so you'd notice the todo is added twice. Your calculation shouldn't change any existing objects, but it's okay to change any *new* objects you created during the calculation. For example, if the `filterTodos` function always returns a *different* array, you can mutate *that* array instead: +O React chama sua função duas vezes, então você notaria que o todo é adicionado duas vezes. Seu cálculo não deve alterar nenhum objeto existente, mas tudo bem alterar quaisquer objetos *novos* que você criou durante o cálculo. Por exemplo, se a função `filterTodos` sempre retornar um array *diferente*, você pode mutar *esse* array em vez disso: ```js {3,4} const visibleTodos = useMemo(() => { const filtered = filterTodos(todos, tab); - // ✅ Correct: mutating an object you created during the calculation + // ✅ Correto: mutando um objeto que você criou durante o cálculo filtered.push({ id: 'last', text: 'Go for a walk!' }); return filtered; }, [todos, tab]); ``` -Read [keeping components pure](/learn/keeping-components-pure) to learn more about purity. +Leia [mantendo os componentes puros](/learn/keeping-components-pure) para saber mais sobre pureza. -Also, check out the guides on [updating objects](/learn/updating-objects-in-state) and [updating arrays](/learn/updating-arrays-in-state) without mutation. +Além disso, confira os guias sobre [atualização de objetos](/learn/updating-objects-in-state) e [atualização de arrays](/learn/updating-arrays-in-state) sem mutação. --- -### My `useMemo` call is supposed to return an object, but returns undefined {/*my-usememo-call-is-supposed-to-return-an-object-but-returns-undefined*/} +### Minha chamada `useMemo` é suposta retornar um objeto, mas retorna undefined {/*my-usememo-call-is-supposed-to-return-an-object-but-returns-undefined*/} -This code doesn't work: +Este código não funciona: ```js {1-2,5} - // 🔴 You can't return an object from an arrow function with () => { + // 🔴 Você não pode retornar um objeto de uma arrow function com () => { const searchOptions = useMemo(() => { matchMode: 'whole-word', text: text }, [text]); ``` -In JavaScript, `() => {` starts the arrow function body, so the `{` brace is not a part of your object. This is why it doesn't return an object, and leads to mistakes. You could fix it by adding parentheses like `({` and `})`: +Em JavaScript, `() => {` inicia o corpo da função de seta, então a chave `{` não faz parte do seu objeto. É por isso que ele não retorna um objeto e leva a erros. Você pode corrigi-lo adicionando parênteses como `({` e `})`: ```js {1-2,5} - // This works, but is easy for someone to break again + // Isso funciona, mas é fácil para alguém quebrar novamente const searchOptions = useMemo(() => ({ matchMode: 'whole-word', text: text }), [text]); ``` -However, this is still confusing and too easy for someone to break by removing the parentheses. +No entanto, isso ainda é confuso e fácil demais para alguém quebrar removendo os parênteses. -To avoid this mistake, write a `return` statement explicitly: +Para evitar esse erro, escreva uma instrução `return` explicitamente: ```js {1-3,6-7} - // ✅ This works and is explicit + // ✅ Isso funciona e é explícito const searchOptions = useMemo(() => { return { matchMode: 'whole-word', @@ -1320,57 +1317,57 @@ To avoid this mistake, write a `return` statement explicitly: --- -### Every time my component renders, the calculation in `useMemo` re-runs {/*every-time-my-component-renders-the-calculation-in-usememo-re-runs*/} +### Toda vez que meu componente renderiza, o cálculo em `useMemo` é executado novamente {/*every-time-my-component-renders-the-calculation-in-usememo-re-runs*/} -Make sure you've specified the dependency array as a second argument! +Certifique-se de ter especificado o array de dependência como o segundo argumento! -If you forget the dependency array, `useMemo` will re-run the calculation every time: +Se você esquecer o array de dependência, `useMemo` executará novamente o cálculo toda vez: ```js {2-3} function TodoList({ todos, tab }) { - // 🔴 Recalculates every time: no dependency array + // 🔴 Recalcula toda vez: nenhum array de dependência const visibleTodos = useMemo(() => filterTodos(todos, tab)); // ... ``` -This is the corrected version passing the dependency array as a second argument: +Esta é a versão corrigida passando o array de dependência como um segundo argumento: ```js {2-3} function TodoList({ todos, tab }) { - // ✅ Does not recalculate unnecessarily + // ✅ Não recalcula desnecessariamente const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]); // ... ``` -If this doesn't help, then the problem is that at least one of your dependencies is different from the previous render. You can debug this problem by manually logging your dependencies to the console: +Se isso não ajudar, o problema é que pelo menos uma de suas dependências é diferente da renderização anterior. Você pode depurar este problema registrando manualmente suas dependências no console: ```js const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]); console.log([todos, tab]); ``` -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 clicar com o botão direito do mouse nos arrays de diferentes novas renderizações no console e selecionar "Armazenar como variável global" para ambos. Supondo que o primeiro tenha sido salvo como `temp1` e o segundo tenha sido salvo como `temp2`, você pode usar o console do navegador para verificar se cada dependência em ambos os arrays é 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 entre os arrays? +Object.is(temp1[1], temp2[1]); // A segunda dependência é a mesma entre os arrays? +Object.is(temp1[2], temp2[2]); // ... e assim por diante para cada dependência ... ``` -When you find which dependency breaks memoization, either find a way to remove it, or [memoize it as well.](#memoizing-a-dependency-of-another-hook) +Quando você descobrir qual dependência quebra a memoização, encontre uma maneira de removê-la ou [memorize-a também.](#memoizing-a-dependency-of-another-hook) --- -### I need to call `useMemo` for each list item in a loop, but it's not allowed {/*i-need-to-call-usememo-for-each-list-item-in-a-loop-but-its-not-allowed*/} +### Preciso chamar `useMemo` para cada item da lista em um loop, mas não é permitido {/*i-need-to-call-usememo-for-each-list-item-in-a-loop-but-its-not-allowed*/} -Suppose the `Chart` component is wrapped in [`memo`](/reference/react/memo). You want to skip re-rendering every `Chart` in the list when the `ReportList` component re-renders. However, you can't call `useMemo` in a loop: +Suponha que o componente `Chart` esteja envolvido em [`memo`](/reference/react/memo). Você quer pular a renderização de cada `Chart` na lista quando o componente `ReportList` renderizar novamente. No entanto, você não pode chamar `useMemo` em um loop: ```js {5-11} function ReportList({ items }) { return (
{items.map(item => { - // 🔴 You can't call useMemo in a loop like this: + // 🔴 Você não pode chamar useMemo em um loop como este: const data = useMemo(() => calculateReport(item), [item]); return (
@@ -1383,7 +1380,7 @@ function ReportList({ items }) { } ``` -Instead, extract a component for each item and memoize data for individual items: +Em vez disso, extraia um componente para cada item e memorize dados para itens individuais: ```js {5,12-18} function ReportList({ items }) { @@ -1397,7 +1394,7 @@ function ReportList({ items }) { } function Report({ item }) { - // ✅ Call useMemo at the top level: + // ✅ Chame useMemo no nível superior: const data = useMemo(() => calculateReport(item), [item]); return (
@@ -1407,7 +1404,7 @@ function Report({ item }) { } ``` -Alternatively, you could remove `useMemo` and instead wrap `Report` itself in [`memo`.](/reference/react/memo) If the `item` prop does not change, `Report` will skip re-rendering, so `Chart` will skip re-rendering too: +Alternativamente, você pode remover `useMemo` e, em vez disso, envolver o próprio `Report` em [`memo`.](/reference/react/memo) Se a prop `item` não mudar, `Report` pulará a renderização novamente, então `Chart` pulará a renderização novamente também: ```js {5,6,12} function ReportList({ items }) { @@ -1421,5 +1418,4 @@ const Report = memo(function Report({ item }) {
); -}); -``` +}); \ No newline at end of file From d9d7bd4f592f86dcd09155fc4a320aa44f4b3ae1 Mon Sep 17 00:00:00 2001 From: Nivaldo Farias Date: Thu, 20 Mar 2025 13:36:24 -0300 Subject: [PATCH 2/2] Update useMemo.md - remove indent spaces - add and remove codeblock fences --- src/content/reference/react/useMemo.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/content/reference/react/useMemo.md b/src/content/reference/react/useMemo.md index 268b9202e..de0734cf8 100644 --- a/src/content/reference/react/useMemo.md +++ b/src/content/reference/react/useMemo.md @@ -79,8 +79,8 @@ function TodoList({ todos, tab, theme }) { Você precisa passar duas coisas para `useMemo`: -1. Uma função de cálculo que não recebe argumentos, como `() =>`, e retorna o que você queria calcular. -2. Uma lista de dependências incluindo cada valor dentro do seu componente que é usado dentro do seu cálculo. +1. Uma função de cálculo que não recebe argumentos, como `() =>`, e retorna o que você queria calcular. +2. Uma lista de dependências incluindo cada valor dentro do seu componente que é usado dentro do seu cálculo. Na renderização inicial, o valor que você obterá de `useMemo` será o resultado da chamada da sua cálculo. @@ -147,19 +147,19 @@ Se seu app for como este site e a maioria das interações for grosseira (como s Otimizar com `useMemo` só é valioso em alguns casos: -* O cálculo que você está colocando em `useMemo` é notavelmente lento e suas dependências raramente mudam. -* Você o passa como uma prop para um componente encapsulado em [`memo`.](/reference/react/memo) Você quer pular a re-renderização se o valor não tiver mudado. A memoization permite que seu componente renderize novamente apenas quando as dependências não são as mesmas. -* O valor que você está passando é posteriormente usado como uma dependência de algum Hook. Por exemplo, talvez outro valor de cálculo `useMemo` dependa dele. Ou talvez você esteja dependendo desse valor de [`useEffect.`](/reference/react/useEffect) +* O cálculo que você está colocando em `useMemo` é notavelmente lento e suas dependências raramente mudam. +* Você o passa como uma prop para um componente encapsulado em [`memo`.](/reference/react/memo) Você quer pular a re-renderização se o valor não tiver mudado. A memoization permite que seu componente renderize novamente apenas quando as dependências não são as mesmas. +* O valor que você está passando é posteriormente usado como uma dependência de algum Hook. Por exemplo, talvez outro valor de cálculo `useMemo` dependa dele. Ou talvez você esteja dependendo desse valor de [`useEffect.`](/reference/react/useEffect) Não há nenhum benefício em encapsular um cálculo em `useMemo` em outros casos. Também não há nenhum dano significativo em fazer isso, então algumas equipes optam por não pensar em casos individuais e memorizar o máximo possível. A desvantagem dessa abordagem é que o código se torna menos legível. Além disso, nem toda memoization é eficaz: um único valor que é "sempre novo" é suficiente para quebrar a memoization para um componente inteiro. **Na prática, você pode tornar muita memoization desnecessária seguindo alguns princípios:** -1. Quando um componente envolve visualmente outros componentes, deixe-o [aceitar JSX como filhos.](/learn/passing-props-to-a-component#passing-jsx-as-children) Dessa forma, quando o componente wrapper atualiza seu próprio state, o React sabe que seus filhos não precisam renderizar novamente. -2. Prefira o state local e não [eleve o state](/learn/sharing-state-between-components) mais do que o necessário. Por exemplo, não mantenha o state transitório, como formulários e se um item está em hover, no topo da sua árvore ou em uma biblioteca de state global. -3. Mantenha sua [lógica de renderização pura.](/learn/keeping-components-pure) Se renderizar novamente um componente causar um problema ou produzir algum artefato visual perceptível, é um erro no seu componente! Corrija o erro em vez de adicionar memoization. -4. Evite [Effects desnecessários que atualizam o state.](/learn/you-might-not-need-an-effect) A maioria dos problemas de desempenho em aplicativos React é causada por cadeias de atualizações originadas de Effects que fazem seus componentes renderizarem repetidamente. -5. Tente [remover dependências desnecessárias de seus Effects.](/learn/removing-effect-dependencies) Por exemplo, em vez de memoization, muitas vezes é mais simples mover algum objeto ou uma função dentro de um Effect ou fora do componente. +1. Quando um componente envolve visualmente outros componentes, deixe-o [aceitar JSX como filhos.](/learn/passing-props-to-a-component#passing-jsx-as-children) Dessa forma, quando o componente wrapper atualiza seu próprio state, o React sabe que seus filhos não precisam renderizar novamente. +2. Prefira o state local e não [eleve o state](/learn/sharing-state-between-components) mais do que o necessário. Por exemplo, não mantenha o state transitório, como formulários e se um item está em hover, no topo da sua árvore ou em uma biblioteca de state global. +3. Mantenha sua [lógica de renderização pura.](/learn/keeping-components-pure) Se renderizar novamente um componente causar um problema ou produzir algum artefato visual perceptível, é um erro no seu componente! Corrija o erro em vez de adicionar memoization. +4. Evite [Effects desnecessários que atualizam o state.](/learn/you-might-not-need-an-effect) A maioria dos problemas de desempenho em aplicativos React é causada por cadeias de atualizações originadas de Effects que fazem seus componentes renderizarem repetidamente. +5. Tente [remover dependências desnecessárias de seus Effects.](/learn/removing-effect-dependencies) Por exemplo, em vez de memoization, muitas vezes é mais simples mover algum objeto ou uma função dentro de um Effect ou fora do componente. Se uma interação específica ainda parecer lenta, [use o React Developer Tools profiler](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html) para ver quais componentes se beneficiariam mais da memoization e adicione memoization onde for necessário. Esses princípios tornam seus componentes mais fáceis de depurar e entender, por isso é bom segui-los em qualquer caso. A longo prazo, estamos pesquisando [fazer memoization granularmente automaticamente](https://www.youtube.com/watch?v=lGEMwh32soc) para resolver isso de uma vez por todas. @@ -627,7 +627,6 @@ export default function TodoList({ todos, tab, theme }) { ); } ``` -``` O comportamento seria o mesmo. Se os `visibleTodos` não mudaram, `List` não será renderizado novamente. Um nó JSX como `` é um objeto como `{ type: List, props: { items: visibleTodos } }`. Criar este objeto é muito barato, mas o React não sabe se seu conteúdo é o mesmo da última vez ou não. É por isso que, por padrão, o React irá renderizar novamente o componente `List`. @@ -1418,4 +1417,5 @@ const Report = memo(function Report({ item }) {
); -}); \ No newline at end of file +}); +```