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*/}]);
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>;
});
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]);
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>
</>
);
};
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);
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;
}
}
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>
</>
);
};
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} />;
};
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>
);
};
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
Top comments (0)