Explorando os Hooks Adicionais do React: Exemplos e Casos de Uso

jhonyaraujooficial

Jhonata Vinicius Da Silva Araujo

Posted on May 23, 2023

Explorando os Hooks Adicionais do React: Exemplos e Casos de Uso

Introdução:

O React é uma biblioteca JavaScript amplamente utilizada para a construção de interfaces de usuário interativas. Desde a introdução dos Hooks no React 16.8, os desenvolvedores têm desfrutado de uma maneira mais simples e eficiente de compartilhar lógica entre componentes funcionais.

Além dos Hooks básicos, como useState, useEffect e useContext, o React também oferece Hooks adicionais que fornecem funcionalidades extras.

Neste artigo, exploraremos esses Hooks adicionais, discutiremos seus casos de uso e será fornecido exemplos práticos.

useReducer:

O Hook useReducer é uma alternativa ao useState quando se lida com estados mais complexos que envolvem múltiplas transições. Ele aceita um reducer e um estado inicial, retornando o estado atual e uma função dispatch para disparar ações.

É útil quando se trabalha com lógica de estado mais avançada, como gerenciamento de formulários ou estados de aplicativos complexos.

Exemplo:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

useRef:

O Hook useRef retorna um objeto mutável que persiste durante todo o ciclo de vida do componente. É útil para acessar e manter uma referência a um elemento do DOM, armazenar valores mutáveis entre renderizações ou para armazenar qualquer valor que precise ser persistido durante o ciclo de vida do componente.

Exemplo:

import React, { useRef } from 'react';

const InputWithFocus = () => {
  const inputRef = useRef(null);

  const handleClick = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

useMemo:

O Hook useMemo é usado para memorizar o resultado de uma função de cálculo pesado e evitar recalculá-la em cada renderização.

Ele recebe uma função de cálculo e um array de dependências e retorna o valor memorizado. É útil quando o cálculo é computacionalmente intensivo e os valores de entrada não mudam com frequência.

Exemplo:

import React, { useMemo } from 'react';

const ExpensiveCalculation = () => {
  const result = useMemo(() => {
    // Cálculo pesado
    return performExpensiveCalculation();
  }, [dependencies]);

  return <div>Result: {result}</div>;
};

Enter fullscreen mode Exit fullscreen mode

useCallback:

O hook useCallback é usado para memorizar uma função e evitar a criação desnecessária de uma nova instância dessa função a cada renderização do componente.

Ele é útil quando você deseja otimizar o desempenho de componentes que dependem de funções que não precisam ser recriadas sempre que o componente é renderizado.

Vamos explorar abaixo alguns casos de uso e fornecer um exemplo prático.

Casos de Uso:

  1. Passar uma função para um componente filho: Quando um componente pai passa uma função para um componente filho como prop, o uso do useCallback pode evitar que a função seja recriada a cada renderização do componente pai, garantindo que o componente filho só seja atualizado quando realmente necessário.
  2. Otimizar a criação de manipuladores de eventos: Em componentes que possuem eventos que disparam ações complexas ou fazem cálculos intensivos, o useCallback pode ser usado para garantir que o manipulador de eventos seja criado apenas uma vez, evitando renderizações desnecessárias.

Exemplo:

import React, { useCallback, useState, memo } from 'react';

const ChildComponent = memo(({ handleClick }) => {
  // Componente filho que é renderizado quando o handleClick é atualizado
  return <button onClick={handleClick}>Click Me</button>;
});

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>
      <ChildComponent handleClick={handleClick} />
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o hook useCallback é usado para memorizar a função handleClick no componente pai. Dessa forma, mesmo que o componente pai seja renderizado várias vezes, a função handleClick não será recriada, garantindo que o componente filho seja renderizado apenas quando o estado count for atualizado.

useImperativeHandle:

O hook useImperativeHandle é usado para expor funções e propriedades específicas de um componente funcional para componentes pai.

Ele permite que você controle a instância do componente filho e exponha métodos personalizados para serem acessados externamente.

Vamos explorar abaixo alguns casos de uso e fornecer um exemplo prático.

Casos de Uso:

  1. Integração com bibliotecas de terceiros: Em alguns casos, você pode precisar integrar seu componente funcional com uma biblioteca externa que requer o acesso direto a alguns métodos ou propriedades do componente. O useImperativeHandle permite que você exponha apenas o que é necessário, mantendo o controle sobre a interface externa do componente.
  2. Componentes customizados com APIs específicas: Se você está criando um componente personalizado que precisa ser controlado externamente, como um componente de formulário que precisa ser validado ou enviado, o useImperativeHandle pode ser usado para expor métodos relevantes para o controle externo.

Exemplo:

import React, { useRef, useImperativeHandle, forwardRef } from 'react';

// Componente filho que deseja expor um método
const ChildComponent = forwardRef((props, ref) => {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => ({
    focusInput: () => {
      inputRef.current.focus();
    },
  }));

  return <input ref={inputRef} type="text" />;
});

// Componente pai que acessa o método exposto pelo componente filho
const ParentComponent = () => {
  const childRef = useRef(null);

  const handleClick = () => {
    childRef.current.focusInput();
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o hook useImperativeHandle é usado no componente filho para expor o método focusInput. O componente filho utiliza o hook useRef para criar uma referência ao elemento de input e, em seguida, o hook useImperativeHandle é usado para expor o método focusInput através da referência passada como segundo argumento.

No componente pai, um botão é renderizado e, quando clicado, chama o método focusInput exposto pelo componente filho através da referência childRef. Dessa forma, é possível acessar o elemento de input no componente filho e aplicar o foco diretamente.

useLayoutEffect:

O hook useLayoutEffect é bastante semelhante ao useEffect, porém é sincronizado com o ciclo de renderização do React, o que significa que ele é executado imediatamente após as mudanças no DOM serem aplicadas, mas antes do browser concluir a pintura da tela.

Ele é útil em casos em que você precisa realizar tarefas de manipulação de layout que dependem das medidas ou posições dos elementos na tela.

Vamos explorar abaixo alguns casos de uso e fornecer um exemplo prático.

Casos de Uso:

  1. Manipulação de medidas e posições de elementos: O useLayoutEffect pode ser usado quando você precisa obter as medidas ou posições de elementos no DOM que foram atualizadas após a renderização do componente. Por exemplo, se você precisa calcular a altura ou a largura de um elemento ou precisa posicionar um elemento com base em outras medidas.
  2. Atualização de animações ou efeitos visuais: Quando você deseja criar animações ou efeitos visuais que dependem de informações atualizadas de layout, como transições suaves ou animações que envolvem mudanças na posição ou tamanho dos elementos, o useLayoutEffect pode ser usado para garantir que essas atualizações sejam aplicadas antes da pintura da tela.
  3. Interações com bibliotecas externas: Se você está integrando seu componente com uma biblioteca externa que espera que o DOM esteja atualizado antes de realizar determinadas ações, o useLayoutEffect pode ser útil para garantir que as mudanças no DOM sejam aplicadas antes da interação com a biblioteca.

Exemplo:

import React, { useLayoutEffect, useRef } from 'react';

const ComponentWithLayoutEffect = () => {
  const elementRef = useRef(null);

  useLayoutEffect(() => {
    // Obtém as medidas do elemento após a atualização do DOM
    const { width, height } = elementRef.current.getBoundingClientRect();

    // Atualiza algum estado ou realiza alguma ação com base nas medidas obtidas
    console.log(`Largura: ${width}px, Altura: ${height}px`);
  });

  return <div ref={elementRef}>Exemplo de Componente com useLayoutEffect</div>;
};

Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o hook useLayoutEffect é usado para realizar uma ação após a atualização do DOM. O elemento <div> é referenciado usando o hook useRef, permitindo o acesso ao elemento em questão.

Dentro do useLayoutEffect, as medidas do elemento são obtidas usando o método getBoundingClientRect(), que retorna um objeto contendo informações sobre as dimensões e a posição do elemento no viewport.

Neste exemplo, estamos apenas exibindo as medidas no console, mas você pode realizar qualquer ação necessária com base nessas medidas.

É importante ressaltar que o useLayoutEffect é síncrono e bloqueante, o que significa que ele pode causar um atraso na renderização do componente. Portanto, é importante usá-lo com cuidado e considerar se o useEffect seria mais adequado em determinadas situações.

useDebugValue:

O hook useDebugValue é um hook de diagnóstico do React que permite fornecer um rótulo personalizado para um valor customizado, facilitando a identificação e depuração de componentes durante o desenvolvimento.

Ele não tem impacto na renderização ou funcionalidade do componente, mas fornece informações úteis ao utilizar ferramentas de desenvolvimento.

Casos de Uso:

  1. Exibição de informações personalizadas: O useDebugValue pode ser usado para exibir informações personalizadas sobre um valor durante a depuração. Isso é especialmente útil quando você possui um valor complexo ou derivado que deseja inspecionar facilmente enquanto depura seu componente.
  2. Identificação de componentes em ferramentas de desenvolvimento: Ao usar ferramentas de desenvolvimento que suportam o hook useDebugValue , você pode fornecer um rótulo significativo para um componente, tornando mais fácil identificar e distinguir componentes específicos na árvore de componentes.
  3. Visualização de estado interno: Se você tiver algum estado interno no componente que não é diretamente visível no componente renderizado, o useDebugValue pode ser usado para expor esse estado durante a depuração, permitindo uma melhor compreensão do estado interno do componente.

Exemplo:

import React, { useDebugValue, useState } from 'react';

const ComponentWithDebugValue = () => {
  const [count, setCount] = useState(0);

  useDebugValue(`Count: ${count}`);

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <div>
      <button onClick={increment}>Increment</button>
      <p>Count: {count}</p>
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o hook useDebugValue é usado para fornecer um rótulo personalizado para o valor count. Isso significa que, ao inspecionar o componente em ferramentas de desenvolvimento, o rótulo "Count: {valor}" será exibido, facilitando a identificação do estado do contador durante a depuração.

Ao clicar no botão "Increment", o estado count é atualizado e o componente é renderizado novamente. Durante a renderização, o hook useDebugValue garante que o rótulo personalizado seja atualizado, permitindo que você acompanhe facilmente o valor atualizado do contador durante a depuração.

Embora o exemplo acima seja simples, o useDebugValue é particularmente útil em cenários mais complexos, onde você pode ter valores personalizados ou derivados que precisam ser monitorados e inspecionados durante o desenvolvimento.

useDeferredValue:

O hook useDeferredValue é um hook introduzido no React 18 que permite atrasar a atualização de um valor de estado durante a renderização. Ele é útil para otimizar o desempenho de componentes que possuem valores de estado que não precisam ser atualizados imediatamente.

Casos de Uso:

  1. Atualizações não críticas: Se você tiver um valor de estado que é atualizado com frequência, mas as atualizações não são críticas para a renderização imediata do componente, você pode usar o useDeferredValue para atrasar a atualização desse valor. Isso pode melhorar o desempenho, reduzindo a frequência de atualizações e renderizações desnecessárias.
  2. Animações suaves: O useDeferredValue é especialmente útil para criar animações suaves em componentes. Você pode atrasar a atualização do valor de estado usado para controlar a animação, garantindo que a animação seja executada de forma mais fluida e sem interrupções.
  3. Carregamento de dados assíncronos: Se você estiver buscando dados assíncronos e deseja evitar atualizações rápidas do estado enquanto os dados estão sendo buscados, o useDeferredValue pode ser usado para atrasar a atualização do estado até que os dados sejam completamente carregados, evitando renderizações desnecessárias.

Exemplo:

import React, { useState, useDeferredValue } from 'react';

const ComponentWithDeferredValue = () => {
  const [count, setCount] = useState(0);

  const deferredCount = useDeferredValue(count, { timeoutMs: 1000 });

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <div>
      <button onClick={increment}>Increment</button>
      <p>Count: {deferredCount}</p>
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o hook useDeferredValue é usado para atrasar a atualização do valor de estado count por 1 segundo.
Durante esse período, se o estado count for atualizado várias vezes, apenas a última atualização será refletida na renderização do componente.

O valor atrasado deferredCount é utilizado na renderização do componente, garantindo que apenas a atualização mais recente seja refletida no elemento <p>. Isso evita renderizações desnecessárias e melhora o desempenho do componente.

No caso de múltiplas atualizações do estado count dentro do período de atraso, apenas a atualização mais recente será visível após o término do período de atraso.

O useDeferredValue é especialmente útil quando você possui atualizações rápidas e frequentes em um valor de estado, mas deseja otimizar o desempenho do componente, evitando renderizações desnecessárias causadas por atualizações não críticas.

useTransition:

O hook useTransition é um hook introduzido no React 18 que permite adicionar transições suaves a alterações de estado.

Ele é útil para criar animações e efeitos visuais fluidos durante as transições de renderização.

Casos de Uso:

  1. Atualizações intensivas: Quando você tem atualizações de estado intensivas que podem causar interrupções visuais no seu aplicativo, o useTransition pode ser usado para suavizar essas transições. Ele permite que você aguarde um período curto antes de aplicar a atualização no estado, proporcionando uma experiência mais agradável aos usuários.
  2. Transições de carregamento: Se o seu aplicativo exibe elementos de carregamento ou indicadores de progresso, o useTransition pode ser usado para criar uma animação suave durante a transição entre o estado de carregamento e o estado concluído. Isso ajuda a evitar mudanças abruptas na interface do usuário e mantém os usuários engajados durante o processo de carregamento.
  3. Animações de entrada e saída: O useTransition é útil para criar animações de entrada e saída em elementos ou componentes. Por exemplo, você pode usar o hook para aplicar um efeito de desvanecimento ao exibir ou ocultar um modal, ou para animar a aparência de um elemento na tela quando um evento ocorre.

Exemplo:

import React, { useState, useTransition } from 'react';

const ComponentWithTransition = () => {
  const [showContent, setShowContent] = useState(false);
  const [startTransition, isPending] = useTransition({
    timeoutMs: 500, // Duration of the transition
  });

  const handleClick = () => {
    startTransition(() => {
      setShowContent(!showContent);
    });
  };

  return (
    <div>
      <button onClick={handleClick}>
        {showContent ? 'Hide Content' : 'Show Content'}
      </button>
      {isPending ? (
        <p>Loading...</p>
      ) : (
        showContent && <p>Content to be shown or hidden</p>
      )}
    </div>
  );
};

export default ComponentWithTransition;

Enter fullscreen mode Exit fullscreen mode

Quando o botão é clicado, a função handleClick é acionada. Dentro dela, chamamos startTransition e passamos uma função de retorno que atualiza o estado showContent.

Essa função de retorno será envolvida por uma transição, tornando a atualização de estado mais suave visualmente.

No render do componente, renderizamos condicionalmente o conteúdo com base em showContent. Se a transição estiver pendente (durante o período de transição), exibimos uma mensagem de carregamento. Caso contrário, mostramos o conteúdo apenas se showContent for true.

O hook useTransition nos permite adicionar um efeito de transição às atualizações de estado, proporcionando uma experiência visual mais suave para o usuário.

É especialmente útil ao lidar com mudanças intensas de estado ou ao adicionar animações durante as transições de IU.

Observação: O hook useTransition requer a versão 18 ou superior do React

useId:

O hook useId é usado para gerar um identificador único dentro de um componente no React. Ele é útil em casos em que você precisa atribuir um ID a um elemento de forma dinâmica, garantindo que o ID seja exclusivo em várias instâncias desse componente.

O caso de uso mais comum para o useId é quando você está renderizando uma lista de elementos e precisa atribuir um ID único a cada item da lista.

Dessa forma, cada item terá um identificador exclusivo, facilitando a referência e manipulação desses elementos.

Exemplo:

import React from 'react';
import { useId } from 'react-id-generator';

const ListaItens = ({ itens }) => {
  return (
    <ul>
      {itens.map((item) => (
        <Item key={useId()} texto={item} />
      ))}
    </ul>
  );
};

const Item = ({ texto }) => {
  const itemId = useId(); // Gera um ID único para cada item

  return <li id={itemId}>{texto}</li>;
};

const App = () => {
  const itens = ['Item 1', 'Item 2', 'Item 3'];

  return <ListaItens itens={itens} />;
};

export default App;

Enter fullscreen mode Exit fullscreen mode

Nesse exemplo, temos um componente ListaItens que recebe uma array de itens. Em seguida, iteramos sobre cada item usando o método map e, para cada item, usamos o useId() como o valor da propriedade key. Isso garante que cada item na lista tenha um ID exclusivo.

Dentro do componente Item, usamos novamente o useId() para gerar um ID único para cada item individualmente. Em seguida, atribuímos esse ID ao elemento <li> através da propriedade id.

Assim, cada item na lista terá um ID exclusivo gerado pelo useId(), permitindo identificar e manipular facilmente esses elementos de forma independente.

O hook useId é útil em situações em que você precisa gerar IDs únicos dinamicamente, evitando conflitos de ID em componentes renderizados repetidamente.

Conclusão:

Os Hooks adicionais do React fornecem aos desenvolvedores ainda mais flexibilidade e poder para criar componentes funcionais eficientes e reutilizáveis

Referencias

React Hooks
React.dev

💖 💪 🙅 🚩
jhonyaraujooficial
Jhonata Vinicius Da Silva Araujo

Posted on May 23, 2023

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

Sign up to receive the latest update from our blog.

Related