React - O que são hooks | Parte 02
Published: 2022-05-17 15:21:53

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](https://dev.to/nascimento_/react-o-que-sao-hooks-parte-01-29a3).

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.

```jsx
const callbackMemoizado = useCallback(() => {
    //  faça algo
  },[{/* dependências*/}]);
```
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.

```jsx
...
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>;
});

```

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](https://pt-br.reactjs.org/docs/react-api.html#reactmemo), enquanto suas props não forem 'alteradas' esse componente não será renderizado de forma desnecessária.

---

> Documentação Oficial: [useCallback](https://pt-br.reactjs.org/docs/hooks-reference.html#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.

```jsx
const ValorMemoizado = useMemo(() => computeExpensiveValue(a, b), [a, b]);
```
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:

```jsx
...
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>
    </>
  );
};

```

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](https://pt-br.reactjs.org/docs/hooks-reference.html#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:
```jsx
  const [state, dispatch] = useReducer(reducer, initialArg, init);
```

**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 ).

```jsx

// 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;
  }
}
```
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.

```jsx
  ...
  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>
    </>
  );
};
```
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](https://pt-br.reactjs.org/docs/hooks-reference.html#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*:
```jsx
...
const RefExample = () => {
  const inputRef = useRef(null);
  
  return <input ref={inputRef} />;
};
```

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

```jsx
...
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>
  );
};

```
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](https://pt-br.reactjs.org/docs/hooks-reference.html#useref)

---

---

> Documentação Oficial [Introdução aos Hooks](https://pt-br.reactjs.org/docs/hooks-intro.html) | [API de Referência dos Hooks](https://pt-br.reactjs.org/docs/hooks-reference.html#basic-hooks)

> Veja também: [Aprendendo React - The Roadmap!](https://dev.to/nascimento_/apredendo-react-the-roadmap-5fii)

> <sub> *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.* </sub>

---

<p align="center"> Me paga um ☕ ? | pix: <strong>nascimento.dev.io@gmail.com</strong> </p>

---


<h4> <em> Me Sigam :) </em> </h4>

[Linkedin](https://www.linkedin.com/in/nascimento-dev-io/) | [Github](https://github.com/nascimento-dev-io)