diff --git a/docs/Iniciando com React/8.7-useCallback.md b/docs/Iniciando com React/8.7-useCallback.md index 89933eb..cb77d98 100644 --- a/docs/Iniciando com React/8.7-useCallback.md +++ b/docs/Iniciando com React/8.7-useCallback.md @@ -37,7 +37,7 @@ function ProductPage({ productId, referrer, theme }) { Neste exemplo, o componente **ProductPage** é uma pagina na qual o usuário pode fazer a compra de um determinado produto, através do formulário que é disponibilizado, caso não houvesse um useCallback, toda vez que alterasse o tema da aplicação, o componente seria re-renderizado e junto dele o _handleSubmit_. Com o useCallback é possível ver que ao mudar o tema da aplicação a função não sofrerá mudanças e consequentemente não precisará ser `armazenada` novamente. -[Ir para a próxima seção](./9-React%20Error%20Boundaries.md) +[Ir para a próxima seção](./8.8-custom-hooks.md)

diff --git a/docs/Iniciando com React/8.8-custom-hooks.md b/docs/Iniciando com React/8.8-custom-hooks.md new file mode 100644 index 0000000..2c6e85d --- /dev/null +++ b/docs/Iniciando com React/8.8-custom-hooks.md @@ -0,0 +1,138 @@ +

+ + Cabeçalho do repositório representado pelo logotipo da He4rt, simbolizado por um coração roxo, na esquerda e a tipografia '4 noobs by He4rt devs' na direita + +

+ +# **CUSTOM HOOKS: Compartilhando lógica entre componentes** + +## O que é um Custom Hook? + +Hook personalizado é uma função JavaScript na qual é possível reutilizar +sua lógica em diversos componentes da aplicação. Imagine que na sua +aplicação você tem vários componentes que precisam fazer requisições a +uma API, ou salvar algo no local storage. Se você tiver um hook +personalizado que faça tais coisas, não será necessário repetir o mesmo +código várias vezes, apenas chamar o hook. + +Um hook personalizado não é um recurso separado do React, é apenas uma +função comum que usa, por baixo dos panos, hooks nativas como **`useState`** +e **`useEffect`**. + +Hooks personalizados não compartilham estados entre os componentes: cada +componente que utiliza o hook possui seu estado isolado, a função +compartilha apenas a lógica. A função precisa, obrigatoriamente, começar +com a palavra **`use`**, essa convenção avisa o React que aquela função pode +chamar outras hooks internamente, permitindo que ferramentas como o +ESLint verifiquem se as regras das hooks estão sendo seguidas corretamente. + +## Vantagens dos Custom Hooks: + + - **Reutilização de lógica:** Evita duplicar o mesmo código (fetch de API, manipulação de formulário, localStorage, etc.) em vários componentes diferentes. + + - **Componentes mais limpos:** A lógica complexa fica isolada na hook, deixando o componente focado apenas na renderização. + + - **Facilidade de manutenção:** Se precisar corrigir um bug ou mudar uma regra de negócio, você altera em um único lugar (a hook), em vez de em cada componente que repete a lógica. + + - **Testabilidade:** Como a lógica fica separada da interface, fica mais fácil testar a hook isoladamente, sem precisar renderizar todo o componente. + + - **Não quebra a árvore de componentes:** Diferente de HOCs e render props, custom hooks não adicionam camadas extras de componentes na árvore, evitando o "wrapper hell". + + - **Compartilhamento sem acoplamento:** Vários componentes podem usar a mesma lógica sem precisar estar relacionados entre si (não é necessário passar props entre pai e filho). + +## Exemplo Prático: useFetch + +Este hook encapsula toda a lógica de requisição a uma API, controlando +os estados de carregamento, erro e dados retornados. + +### O código: + +```javascript + import { useState, useEffect } from 'react'; + + export function useFetch(url){ + const [data, setData] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect( () => { + if (!url) { + setLoading(false); + return; + } + + let ignore = false; // flag: ignora resultado se o effect já foi limpo + + //Função que busca a API + const fetchData = async () => { + setLoading(true); //Ativa o Loading quando começa a busca + setError(null); // Reseta erros anteriores + + try{ + const response = await fetch(url); + const json = await response.json(); + + if (!ignore) setData(json); + }catch (err){ + if (!ignore) { + setError(err.message); + setData(null); + } + }finally{ + if (!ignore) setLoading(false); + } + }; + + fetchData(); + + // Cleanup: roda quando a url muda ou o componente desmonta. + return () => { + ignore = true; + }; + }, [url]); //UseEffect roda toda vez que a variável url muda. + + //Retorna os estados em forma de objetos, dessa maneira é possível pegar o qual variável quiser. + return { data, loading, error }; + } +``` + +### Como funciona? + + - Recebe uma **`url`** como parâmetro. + - Retorna um objeto com três valores: **`data`** (os dados retornados), + **`loading`** (se a requisição está em andamento) e **`error`** (mensagem de + erro, se houver). + - O **`useEffect`** roda automaticamente sempre que a **`url`** mudar, disparando + uma nova requisição. + +### Usando a hook em um componente: + +```jsx + import {useFetch} from 'caminho_da_funcao' + + function ListaPokemon() { + const { data, loading, error } = useFetch('https://pokeapi.co/api/v2/pokemon'); + + if (loading) return

Carregando...

; + if (error) return

Erro: {error}

; + + return ( + + ); + } +``` +Perceba como o componente ficou mais limpo: Ele não sabe **como** a requisição é feita, apenas **usa** o resultado. + +[Ir para a próxima seção](./9-React%20Error%20Boundaries.md) + +

Made with 💜

+ +

+ + Tipografia com o título '4 noobs by He4rt devs' e o slogan 'Da comunidade para a comunidade 💜' + +