DEV Community

Cover image for React - O que são hooks | Parte 02
Jorge Nascimento
Jorge Nascimento

Posted on • Edited on

React - O que são hooks | Parte 02

Vamos continuar falando sobre os hooks nesse artigo, caso não tenha visto a primeira parte veja React - O que são hooks | Parte 01.

Nesse artigo vamos conhecer os hooks useCallback, useMemo, useReducer e o useRef, existe outros hooks mais esses são os principais e mais comum da API de Hooks.


useCallback

O useCallback serve para memorizar funções e
prevenir que elas sejam recriadas a cada novo render do componente.

Recebe como argumentos, um callback e um array de dependências.

O useCallback retornará uma versão memoizada do callback que só muda se uma das entradas sejam alteradas. Isto é útil quando utilizamos callbacks a fim de otimizar componentes filhos, que dependem da igualdade de referência para evitar renderizações desnecessárias.

const callbackMemoizado = useCallback(() => {
    //  faça algo
  },[{/* dependências*/}]);
Enter fullscreen mode Exit fullscreen mode

No caso de um componente filho execute essa função sem o uso do useCallback, isso fará com que ela seja recriada e assim renderiza novamente o componente pai e também o componente filho mesmo que esse não precise ser renderizado novamente pois não possui atualização do seu estado.

Vamos ao exemplo prático.

...
export const Parent = () => {
  const [state, setState] = useState(0);

  console.log("RE-RENDER PARENT");

  // Não há alteração referencial enquanto não existir alteração nas dependências. 
  const handleClick = useCallback(() => {
    setState((prevState) => prevState + 1);
  }, []);

  return (
    <div>
      <div>{state}</div>
      <Child onClick={handleClick}>
    </div>
  );
};

// Child apenas será re-renderizado quando a referência do callback muda.

const Child = React.memo(({ onClick }) => {

  console.log("RE-RENDER CHILD");

  return <button onClick={onClick}>Incrementar</button>;
});

Enter fullscreen mode Exit fullscreen mode

Temos 2 componentes Parent e o Child, a função de callback do evento é memoizada, sendo assim não é recriada a cada novo render do Parent, e como o Child esta dentro de um React.Memo, enquanto suas props não forem 'alteradas' esse componente não será renderizado de forma desnecessária.


Documentação Oficial: useCallback


useMemo

O useMemo é utilizado para realização de cálculos caros em novas renderizações, ele é semelhante ao useCallback porém retorna a execução da função e não a função memoizada.

const ValorMemoizado = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Enter fullscreen mode Exit fullscreen mode

Sua sintaxe é igual ao useCallback, é fornecido uma função e um array de dependências como argumentos, a diferença é que o useMemo irá executar essa função e seu valor será memoizado, sendo executada novamente apenas quando existir alterações em suas dependências.

Vamos ao exemplo:

...
export const Memo = () => {
  const [value, setValue] = useState(Math.PI);
  const [name, setName] = useState("");

  const valueMemoizado = useMemo(() => {

    console.log("Memo recalculado");

    return value * 1000000e+1000;

  }, [value]);

  return (
    <>
      {/* Aqui o cálculo do valor memoizado é refeito */}
      <div>
        <div>{valueMemoizado}</div>
        <button onClick={() => setValue((prevValue) => prevValue * 100e+100)}>
          Calcular
        </button>
      </div>

      {/* Aqui o cálculo se mantém o mesmo e o cálculo não é refeito*/}
      <div>
        <div>{name}</div>
        <input value={name} onChange={(e) => setName(e.target.value)} />
      </div>
    </>
  );
};

Enter fullscreen mode Exit fullscreen mode

Como demonstra o exemplo, existe uma melhoria de performance com o useMemo evitando recalcular sempre o value mesmo que esse não tenha sido alterado.


Documentação Oficial: useMemo


useReducer

O Reducer é uma alternativa ao useState. useReducer é geralmente preferível em relação ao useState quando se tem uma lógica de estado complexa que envolve múltiplos sub-valores, ou quando o próximo estado depende do estado anterior.

Sintaxe:

  const [state, dispatch] = useReducer(reducer, initialArg, init);
Enter fullscreen mode Exit fullscreen mode

useReducer retorna um array com 2 posições, são elas:

  • state é o estado a ser manipulado.
  • dispatch função que é chamada com parâmetros que aciona a reducer.

Recebe os seguintes argumentos:

  • reducer função reducer do tipo (state, action) => newState e retorna o estado atual.
  • - state estado atual.
  • - action geralmente um objeto passado na chamada da função dispatch.
  • initialArgs valor inicial do state.
  • init é um argumento opcional, uma função que retorna o state inicial.

Vamos a um exemplo substituindo o useState do componente Counter e inserindo um estado de clique que adiciona a quantidade de cliques ( independente se incrementar ou decrementar ).


// Criando argumentos do useReducer
const initialValue = {
  counter: 0,
  clicks: 0,
};

function init(initialValue) {
  return {
    counter: initialValue.counter,
    clicks: 0,
  };
}

function reducer(state, action) {
  switch (action.type) {
    case "plus":
      return {
        counter: state.counter + 1,
        clicks: state.clicks + 1,
      };

    case "minus":
      return {
        counter: state.counter - 1,
        clicks: state.clicks + 1,
      };

    default:
      return state;
  }
}
Enter fullscreen mode Exit fullscreen mode

Essas são os argumentos do hook useReducer, na função reducer utilizamos a action para baseado no tipo realizar um determinado processamento, nesse caso 'plus' para somar e 'minus' para subtrair.

Vamos agora ver o componente Counter e a utilização do hook.

  ...
  const Counter = () => {
  // useReducer
  const [state, dispatch] = useReducer(reducer, initialValue, init);

  return (
    <>
      <p>{state.counter}</p>
      <h4>Cliques: {state.clicks}</h4>
      <button onClick={() => dispatch({ type: "plus" })}>+</button> |{" "}
      <button onClick={() => dispatch({ type: "minus" })}>-</button>
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

A função dispatch é chamando no evento de clique, passando então um objeto com o tipo da operação que será tratado na reducer.


Documentação Oficial: useReducer


useRef

O useRef possibilita o acesso a elemento da DOM através de sua referência, dessa forma você pode manipular esse elemento de forma imperativa, dando um focus, blur e acessando o diretamente.

Para ter o acesso ao elemento você atribui o useRef a uma variável e a inicializa com o argumento do hooks. Em seguida você atribui essa variável ao atributo ref do elemento.

Exemplo:

...
const RefExample = () => {
  const inputRef = useRef(null);

  return <input ref={inputRef} />;
};
Enter fullscreen mode Exit fullscreen mode

Um vez com a referência do elemento podemos acessar o elemento através da propriedade current da inputRef.

...
const RefExample = () => {
  const inputRef = useRef(null);

  function handleClick(){
    console.log(inputRef.current.value);
  }

  return(
    <div>
      <input ref={inputRef} />
      <button onClick={handleClick}>Mostra Valor</button>
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

No exemplo ao clicar no botão o value do input é mostrado no console, e assim você pode acessar qualquer outra propriedade do elemento e manipular conforme desejado.

O valor de current é mutável e não altera durante novas renderização, suas alteração também não causa uma nova renderização no componente.


Documentação Oficial: useRef



Documentação Oficial Introdução aos Hooks | API de Referência dos Hooks

Veja também: Aprendendo React - The Roadmap!

Este post tem como objetivo ajudar quem esta começando no aprendizado de React, além de servir como incentivo no meus estudos de React criando outros posts pra fixação do aprendizado.


Me paga um ☕ ? | pix: nascimento.dev.io@gmail.com


Me Sigam :)

Linkedin | Github

Top comments (0)