Série React Hooks: useImperativeHandle
Tags: react, javascript
Published: 2023-04-25 00:46:45


![React hook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2afduumy7mz8y3cbu66.png)



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](https://dev.to/taisesoares/serie-react-hooks-usedeferredvalue-13d)
- [Série React Hooks: useMemo](https://dev.to/taisesoares/serie-react-hooks-usememo-5pc)
- [Série React Hooks: useCallback](https://dev.to/taisesoares/serie-react-hooks-usecallback-49ap)
- [Série React Hooks: useSyncExternalStore](https://dev.to/taisesoares/serie-react-hooks-usesyncexternalstore-2lpk)
- [Série React Hooks: useRef](https://dev.to/taisesoares/serie-react-hooks-useref-2mjl)

## 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:

```Javascript
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:

```javascript
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:

```javascript
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:

```javascript
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.