---
# System prepended metadata

title: Custom Hooks

---

# Custom Hooks

- Tempo de leitura estimado: 9 minutos.

### O que são `hooks`?

* Hooks são uma adição ao React (a partir da versão 16.8) onde se permite fazer uso do `state` e outras `features` do React sem a criação de `classes`. Mais informações na documentação do React.

* Regras imprescindíveis para o uso de hooks:

    - *Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions.*
    - *Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions. (There is just one other valid place to call Hooks — your own custom Hooks. We’ll learn about them in a moment.)*
    
* Exemplos de Custom Hooks:

1. [useIsMobile](https://codesandbox.io/s/useismobile-k8p9t)

    Esse custom hook aqui pode ser implementado de algumas formas. A conclusão que cheguei é fazer uso tanto da `innerWidth` da window quanto o `userAgent` do navegador, que em conjunto com alguma biblioteca de detecção de dispositivos, nos diga com exatidão onde estamos atuando em termos de responsividade. No exemplo abaixo o hook customizado recebe por parâmetro (análogo ao `constructor` de classe) duas propriedades, uma a largura da janela para ser testada e a segunda o `userAgent`.
    
    obs.: Com os parâmetros desta forma, se torna possível a utilização em sistemas SSR.
    
    ```js
    const isMobile = useIsMobile({
          width: 768,
          customAgent: global.navigator.userAgent
        });
    ```
    
    A largura é diretamente testada contra a `window.innerWidth` e o `userAgent` para este caso, é testado com a biblioteca [ismobilejs](https://github.com/kaimallea/isMobile). O teste pode ser feito manualmente com `RegEx`, por exemplo, sem a necessidade de terceiros.
    
    O uso deste custom hook pode ser feito por demanda, isto é, por página/componente ou pode ser conectado no topo do seu App realizando um disparo à `store` para que todo o sistema fique consciente da mobilidade.
    
    - exemplo conectado à `store`: (obs, qualquer uso de estado causa um re-render, o que talvez não seja interessante para todo o App).
    
        ```js
        export const App = () => {
          const isMobile = useIsMobile({
            width: 768,
            customAgent: global.navigator.userAgent
          });
          const dispatch = useDispatch();

          dispatch(setIsMobile(isMobile));
         }
        ```
        
    - exemplo utilizado por demanda:

        ```js
        function App() {
          const isMobile = useIsMobile({
            width: 768,
            customAgent: global.navigator.userAgent
          });

          return (
            <div className="App">
              <h1>{isMobile ? "This is on mobile" : "This is on desktop"}</h1>
            </div>
          );
        }
        ```
        
    Este custom hook faz uso de:
    1. useState
    2. useEffect
    
2. [useModalWrapper](https://codesandbox.io/s/usemodal-as-a-wrapper-uit30)

    Este custom hook faz uso da habilidade de [`Portals`](https://reactjs.org/docs/portals.html) do React onde se é possível montar um componente em qualquer outro lugar do DOM independente de contexto. Novamente, em analogia a um construtor, como parâmetro `bindToElement` é passado o nó desejado para a renderização.

    Este custom hook nos retorna as seguintes propriedades:

    1. ModalWrapper, que nada mais nada menos é, um HOC.
    2. isOpen, como o nome mesmo já diz, nos informa se a modal está aberta ou não.
    3. openModal, atuando diretamente como controle para a abertura da modal.
    4. closeModal, assim como a openModal porém para seu fechamento.
    
    Sua aplicação é bem direta, monte o Wrapper dentro de seu componente e coloque a modal desejada (isso pode variar de aplicação para aplicação e consequentemente sua estilização CSS também no quesito de posicionamento).
    O Wrapper recebe por `props` duas coisas: o `backdrop` e o `fade`, sendo o segundo apenas possível com o primeiro.
    O primeiro disponibiliza a habilidade de clicar fora da modal para seu fechamento (ou apertar ESC ou qualquer outra condicional) e o segundo cria uma janela translúcida por trás (puramente estilo).
    
    ```js
    const {ModalWrapper, isOpen, openModal, closeModal} = useModalWrapper({
      bindToElement: global.document.getElementById('modal-root')
    });

    {
      isOpen && (
        <ModalWrapper backdrop={true} fade={true}>
          <MyBeautifulModal closeModal={closeModal} />
        </ModalWrapper>
      );
    }
    <button type="button" onClick={() => openModal()}>
      Click to Open
    </button>
    ```
    
    Este custom hook faz uso de:
    1. useState
    2. useEffect
    3. useRef
    4. React e ReactDOM

3. [useIsLoading](https://codesandbox.io/s/useisloading-connected-9s8gt)
    
    Observação: idealmente utilizado com aplicações com gerenciamento de estado global como por exemplo o `redux`.

    Este custom hook eu diria até que chega a ser perfumaria no entanto achei interessante por duas razões, abstração de código assim como todos os demais hooks nos oferecem e independência do acesso à `store`. Fica bem simplificado seu uso.
    O componente que necessitar do Loading a partir de alguma ação assíncrona não precisará acessar a `store` de forma alguma.
    
    ```js
    const [isLoading, Loading] = useIsLoading();

      if (isLoading) return <Loading />;
      return <MyComponentAfterLoading />;
    ```

    Este custom hook faz uso de:
    1. React
    2. useSelector (react-redux)
    3. Componente de Loading

4. useAuth

    Este custom hook pode ser implementado de diversas formas e isso pode variiar de acordo com a necessidade e implementação de cada projeto, no entanto a sua ideia é basicamente a mesma, prover mecanismos de autenticação para páginas.
    O custom hook useAuth pode retornar os métodos e propriedades abaixo diretamente ou pode-se dividir suas responsabilidades, conforme abaixo.
    
    ```js
    const {isLogged, doLogin, authInfo} = useLogin();
    const {doLogout} = useLogout();
    ```
    
    As propriedades acima descritas abaixo:
    
    1. isLogged, retorna verdadeiro ou falso para a condicional de autenticado ou não no sistema.
    2. doLogin, dispara a ação para realizar a autenticação.
    3. authInfo, retorna objeto com informações pertinentes à autenticação.
    4. doLogout, dispara a ação pertinente para deslogar do sistema.

    Este custom hook faz uso de:
    1. useEffect
    2. useSelector e useDispatch (react-redux)
    3. useHistory, useLocation (react-router-dom)

5. [useInput](http://codesandbox.io/s/useinput-v66nu)

    Este custom hook é também bem simples no entanto um tanto quanto útil quando se é preciso lidar com `inputs` de formulário.
    Bem direto, o custom hook retorna os valores dos inputs e o `handler` de `onChange`. A mágica do controle de estado está toda por dentro do `useInput`.
    
    ```
    const [values, handleChange] = useInput();

        function handleSubmit(e) {
          e.preventDefault();
          console.log("values", values);
        }

        <form onSubmit={handleSubmit}>
            <input
              type="text"
              name="name"
              placeHolder="Name"
              onChange={handleChange}
            />
        </form>
    ```
    
    Este custom hook faz uso de:
    1. useState

Demais possibilidades:

https://usehooks.com/