React Hook - useInterval
O hook personalizado useInterval
é uma implementação que aborda um desafio comum ao utilizar o setInterval
em conjunto com os React Hooks. O problema principal reside na natureza imperativa do setInterval
, que muitas vezes entra em conflito com o modelo de programação declarativa dos React Hooks.
Ao usar o setInterval
de maneira direta em um componente funcional do React, enfrentamos problemas relacionados à reexecução dos efeitos após cada renderização. Isso ocorre porque o setInterval
não se encaixa perfeitamente no modelo de programação declarativa dos React Hooks. A reexecução frequente de efeitos pode causar interferências no timing do setInterval
, resultando em comportamentos inesperados.
Vamos analisar a implementação do useInterval
passo a passo:
1. Importação de Hooks e criação do Hook
import { useEffect, useRef } from 'react';
function useInterval(callback, delay) {
// Implementação do hook aqui
}
2. Utilização do useRef
const savedCallback = useRef();
O useRef
é utilizado para manter uma referência mutável persistente entre as renderizações do componente. Neste caso, ele é usado para armazenar a função de callback do intervalo.
3. Efeito para salvar o callback atual
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
Este efeito é acionado sempre que o callback
muda. Ele atualiza o current
de savedCallback
com a função de callback mais recente.
4. Efeito para configurar o intervalo
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
Este segundo efeito é acionado sempre que o delay
muda. Se delay
não for nulo, ele configura um intervalo chamando o tick
(que, por sua vez, chama o savedCallback
). Além disso, retorna uma função de limpeza que é executada quando o componente é desmontado, garantindo que o intervalo seja limpo.
5. Uso do Hook em um componente
// useInterval.js
import { useEffect, useRef } from 'react';
function useInterval(callback, delay) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
import React, { useState } from 'react';
import useInterval from './useInterval';
function Counter() {
const [count, setCount] = useState(0);
useInterval(() => {
setCount(count + 1);
}, 1000);
return <h1>{count}</h1>;
}
export default Counter;
O useInterval
encapsula a complexidade associada ao uso de setInterval
em um ambiente React, garantindo que o intervalo seja tratado corretamente durante o ciclo de vida do componente. Ele fornece uma maneira mais declarativa e fácil de lidar com operações baseadas em intervalo de tempo em seus componentes React.