Olá pessoas, vamos iniciar uma séria somente com os hooks existentes no ReactJs. Nesse primeiro capitulo vamos falar do hook useImperativeHandle
. bora la?
Caso queriam ver os outros artigos sobre essa série, segue links de artigos anteriores:
- Série React Hooks: useDeferredValue
- Série React Hooks: useMemo
- Série React Hooks: useCallback
- Série React Hooks: useSyncExternalStore
- Série React Hooks: useRef
useImperativeHandle
No React, componentes são os blocos de construção de uma aplicação. Eles são peças de código reutilizáveis que encapsulam um conjunto de funcionalidades e podem ser compostos juntos para formar uma aplicação. Porém, muitas vezes, precisamos interagir com um componente de fora de seu componente pai. É aí que o useImperativeHandle entra em jogo.
Esse hook é utilizado para expor uma instância de um componente filho para um componente pai, permitindo que o pai possa chamar métodos ou acessar propriedades da instância do filho diretamente. Essa é uma maneira de expor uma determinada parte da API de um componente para seu componente pai. Para usar o useImperativeHandle, você precisa primeiro criar uma referência ao componente filho usando o hook useRef
(Calma! esse fica para um próximo artigo, prometo).
Bora para o primeiro exemplo
saca só pessoal, imagine que você está desenvolvendo um componente que representa um cronômetro, e esse componente tem um botão de "start"
. Quando o botão é clicado, o cronômetro deve começar a contar.
Para implementar essa funcionalidade, você precisa acessar diretamente a instância do componente que representa o cronômetro, para poder chamar o método start()
a partir do componente pai. É aí que entra o useImperativeHandle
!
O hook useImperativeHandle
é utilizado para definir quais métodos e propriedades devem ser expostos para o componente pai através da referência. Vamos ver um exemplo:
import { forwardRef, useImperativeHandle } from 'react';
export default const Stopwatch = forwardRef((props, ref) => {
const [seconds, setSeconds] = useState(0);
const [paused, setPaused] = useState(true);
const start = () => {
setPaused(false);
};
useInterval(() => {
if (!paused) {
setSeconds(seconds + 1);
}
}, 1000);
useImperativeHandle(ref, () => ({
start,
seconds,
}));
return (
<div>
<p>{seconds} seconds</p>
<button onClick={start}>Start</button>
</div>
);
});
Nesse exemplo, o componente Stopwatch
utiliza o hook useImperativeHandle
para expor os métodos start()
e seconds
para o componente pai. O método start()
inicia o cronômetro e a propriedade seconds
representa a quantidade de segundos que o cronômetro está contando.
No componente pai, podemos utilizar a referência passada para o componente Stopwatch
para chamar o método start()
e acessar a propriedade seconds
diretamente, da seguinte maneira:
import { useRef } from 'react';
import Stopwatch from './Stopwatch';
const App = () => {
const stopwatchRef = useRef();
const handleStart = () => {
stopwatchRef.current.start();
};
return (
<div>
<Stopwatch ref={stopwatchRef} />
<button onClick={handleStart}>Iniciar cronômetro</button>
</div>
);
};
export default App;
Perceba agora que o componente pai possui uma referência para o componente Stopwatch
, que pode ser passada como propriedade para o componente filho. Quando o botão é clicado, o método start()
é chamado a partir da referência do componente Stopwatch
.
Ainda confuso, vamos para um outro exemplo
Imagine que tenhamos um componente filho chamado TextInput
e queremos acessar seu método focus()
de seu componente pai, algo da seguinte maneira:
import { useRef, useImperativeHandle, forwardRef } from 'react';
const TextInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return (
<input type="text" ref={inputRef} />
);
});
export default TextInput;
Legal, o que fizemos acima foi criar um componente TextInput
que recebe uma referência como prop. Depois o que fazemos é usar o useRef
para criar uma referência ao elemento input e, então, usamos o useImperativeHandle
para expor o método focus()
do elemento input para seu componente pai.
Note que o useImperativeHandle
recebe dois argumentos, sendo:
- O primeiro argumento é a referência que queremos expor
- Já o segundo argumento é uma função que retorna um objeto contendo os métodos que queremos expor.
Com isso, queremos expor o método focus()
do elemento input, então criamos um objeto com um método focus()
que chama o método focus()
do elemento input. (focus que chama focus, ficou confuso né? Calma meu pequeno gafanhoto, já vai ficar claro).
Bora, agora que criamos o componente TextInput
com o hook useImperativeHandle
, podemos usá-lo em seu componente pai e chamar seu método focus()
diretamente da seguinte maneira:
import { useRef } from 'react';
import TextInput from './TextInput';
function App() {
const textInputRef = useRef(null);
const handleClick = () => {
textInputRef.current.focus();
};
return (
<div>
<button onClick={handleClick}>Focus Input</button>
<TextInput ref={textInputRef} />
</div>
);
}
export default App;
Agora note, que criamos um componente pai chamado App
que renderiza um botão e o componente TextInput
. Então criamos uma referência ao componente TextInput
usando o useRef
e, em seguida, o passamos como uma prop
para o componente TextInput
.
Com isso, quando o botão é clicado, chamamos o método focus()
do componente TextInput
diretamente por meio de sua referência.
Partiu resumo
Resumindo o hook useImperativeHandle
é utilizado para definir quais métodos e propriedades devem ser expostos para o componente pai através da referência.
Ele permite aos desenvolvedores expor métodos específicos de um componente filho para seu componente pai. É particularmente útil quando precisamos interagir com um componente filho de fora de seu componente pai. Usando o useRef
para criar uma referência ao componente filho e o useImperativeHandle
para expor seus métodos, podemos acessar e chamar esses métodos diretamente em seu componente pai.
Isso é tudo pessoal, espero que esse primeiro artigo de uma série sobre os hooks do ReactJS tenha exclarecido qualquer dúvida.
Até a próxima da série.
Top comments (0)