Série React Hooks: useDeferredValue
Taise Soares
Posted on May 22, 2023
Olá pessoas, como prometido bora continuar nossa série com os Hooks do ReactJs.
Caso queriam ver os outros artigos sobre essa série, segue links de artigos anteriores:
- Série React Hooks: useImperativeHandle
- Série React Hooks: useMemo
- Série React Hooks: useCallback
- Série React Hooks: useSyncExternalStore
- Série React Hooks: useRef
E hoje vamos falar de um Hook, tecnicamente novo, lançado na versão 18 chamado useDeferredValue
. Mas vamos para a definição na doc oficial do react:
useDeferredValue is a React Hook that lets you defer updating a part of the UI. - Doc ReactJS
Não disse muita coisa né? Simplificando o useDeferredValue
é um hook do React que permite que você adie a atualização de um valor. Isso pode ser útil quando você quer evitar que a interface do usuário fique lenta ou travada devido a operações pesadas ou demoradas (imagine um filtro enorme ou um campo de pesquisa que retorne muitos dados)
Legal mas como ele funciona ?
O useDeferredValue
recebe dois argumentos: o valor que você deseja adiar e um objeto de configuração com a propriedade timeoutMs
, que define o tempo máximo de adiamento em milissegundos. O hook retorna o valor adiado, que será atualizado após o tempo especificado.
Vamos a um exemplo sem a utilização do useDeferredValue
ok. Neste exemplo, vamos criar de forma genérica uma lista de itens gerada por um loop for com um limite size, a filtragem da lista de itens ocorre a cada renderização, o que pode causar atrasos na entrada de texto se a lista for muito grande.
import React, { useState } from 'react';
interface Item {
id: number;
name: string;
}
const generateItems = (size: number): Item[] => {
const items: Item[] = [];
for (let i = 0; i < size; i++) {
items.push({ id: i, name: `Item ${i}` });
}
return items;
};
const items = generateItems(1000); // Gera uma lista de 1000 itens
const App: React.FC = () => {
const [search, setSearch] = useState('');
const filteredItems = items.filter(item => item.name.includes(search));
return (
<div>
<input
type="text"
value={search}
onChange={e => setSearch(e.target.value)}
/>
<ul>
{filteredItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
};
export default App;
Note que nesse exemplo, estamos usando a função generateItems
para gerar uma lista de 1000 itens. A filtragem da lista de itens ocorre com base no valor search sem usar o hook useDeferredValue
. Isso pode causar atrasos na entrada de texto se a lista for muito grande ou a filtragem for complexa, já que a filtragem ocorre a cada renderização.
Agora vamos ao mesmo exemplo, porém utilizando o hook useDeferredValue
para demonstrar a melhoria na responsividade do componente.
import React, { useState, useDeferredValue } from 'react';
interface Item {
id: number;
name: string;
}
const generateItems = (size: number): Item[] => {
const items: Item[] = [];
for (let i = 0; i < size; i++) {
items.push({ id: i, name: `Item ${i}` });
}
return items;
};
const items = generateItems(1000); // Gera uma lista de 1000 itens
const App: React.FC = () => {
const [search, setSearch] = useState('');
const deferredSearch = useDeferredValue(search, { timeoutMs: 200 });
const filteredItems = items.filter(item => item.name.includes(deferredSearch));
return (
<div>
<input
type="text"
value={search}
onChange={e => setSearch(e.target.value)}
/>
<ul>
{filteredItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
};
export default App;
Agora, criamos uma função generateItems
que recebe um parâmetro size
e gera uma lista de itens com base nesse tamanho. A função é usada para gerar uma lista de 1000 itens, que é então filtrada com base no valor adiado deferredSearch
usando o hook useDeferredValue
. Isso permite que o React adie a atualização da lista de itens enquanto o usuário digita no campo de entrada, melhorando a responsividade do componente.
Ah legal mas como eu testo se isso é verdade?
Bora fazer o teste? No primeiro exemplo ao renderizar em seu navegador (vou supor que você esteja utilizando no chrome), abra o seu devTools e vá na aba de Performance
. Apos isso click na engrenagem
ao lado das opções e altere a CPU para 6x slowdown
.
Depois faça o teste com ambos os projetos e notara a diferença de performance entre eles.
Legal mas quando devo usa-lo?
Você pode usar o useDeferredValue
em cenários onde a atualização imediata de um valor pode causar lentidão na interface do usuário. Por exemplo, ao filtrar uma lista grande de itens enquanto o usuário digita em um campo de pesquisa.
Conclusão
Ao utilizar o useDeferredValue
, você ganha em performance, pois a atualização do valor é adiada, evitando que a interface fique lenta devido a operações pesadas ou demoradas. Por outro lado, ao não utilizar o useDeferredValue
, a performance pode ser afetada negativamente, pois a atualização do valor é imediata e pode causar lentidão na interface do usuário.
É importante lembrar que o ganho de performance ao utilizar o useDeferredValue
depende do cenário e da complexidade das operações realizadas. Em alguns casos, o ganho pode ser significativo, enquanto em outros, pode ser mínimo.
Posted on May 22, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.