Série React Hooks: useDeferredValue
Tags: react, javascript, usedeferredvalue
Published: 2023-05-22 12:06:22


![Hook React](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40nq2bmp8x6eummoc4m4.png)

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](https://dev.to/taisesoares/serie-react-hooks-useimperativehandle-44d)
- [Série React Hooks: useMemo](https://dev.to/taisesoares/serie-react-hooks-usememo-5pc)
- [Série React Hooks: useCallback](https://dev.to/taisesoares/serie-react-hooks-usecallback-49ap)
- [Série React Hooks: useSyncExternalStore](https://dev.to/taisesoares/serie-react-hooks-usesyncexternalstore-2lpk)
- [Série React Hooks: useRef](https://dev.to/taisesoares/serie-react-hooks-useref-2mjl)

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](https://react.dev/reference/react/useDeferredValue)

![whats](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ix6t0e150clpbu45g0m.gif)

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`. 


![devtools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/um2kkrkfv1mvduzdivv0.png)

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.