Série React Hooks: useDeferredValue

taisesoares

Taise Soares

Posted on May 22, 2023

Série React Hooks: useDeferredValue

Hook React

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:

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

whats

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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

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.

💖 💪 🙅 🚩
taisesoares
Taise Soares

Posted on May 22, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related