From edec00ac6a709b385fc2106cf53fe4f605d36dcf Mon Sep 17 00:00:00 2001 From: dvbcknd <189028215+dvbcknd@users.noreply.github.com> Date: Wed, 8 Jul 2026 16:08:53 -0300 Subject: [PATCH 1/4] docs: adiciona artigo sobre custom hooks --- docs/Custom Hooks/custom-hooks.md | 134 ++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 docs/Custom Hooks/custom-hooks.md diff --git a/docs/Custom Hooks/custom-hooks.md b/docs/Custom Hooks/custom-hooks.md new file mode 100644 index 0000000..aeec01c --- /dev/null +++ b/docs/Custom Hooks/custom-hooks.md @@ -0,0 +1,134 @@ +

+ + 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(true); + const [error, setError] = useState(null); + + useEffect( () => { + //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); + if (!response.ok){ + throw new Error("Erro ao buscar a API"); + } + const json = await response.json(); + setData(json); //Guarda os dados. + }catch (err){ + setError(err.message); //Guarda o erro, caso aconteça. + setData(null); + }finally{ + setLoading(false); + } + }; + + if(!url){ + return; + }else{ + fetchData(); //Se tiver URL ele chama a função + } + }, [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 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. + +
Made with 💜
+ +

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

From 26aa7c3e927cc52ed611f7fdd0ec02802fdd9646 Mon Sep 17 00:00:00 2001 From: Bruno Gomes <189028215+dvbcknd@users.noreply.github.com> Date: Wed, 8 Jul 2026 16:12:06 -0300 Subject: [PATCH 2/4] Update custom-hooks.md Signed-off-by: Bruno Gomes <189028215+dvbcknd@users.noreply.github.com> --- docs/Custom Hooks/custom-hooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Custom Hooks/custom-hooks.md b/docs/Custom Hooks/custom-hooks.md index aeec01c..47048fb 100644 --- a/docs/Custom Hooks/custom-hooks.md +++ b/docs/Custom Hooks/custom-hooks.md @@ -125,7 +125,7 @@ os estados de carregamento, erro e dados retornados. Perceba como o componente ficou mais limpo: Ele não sabe **como** a requisição é feita, apenas **usa** o resultado. -
Made with 💜
+

Made with 💜

From f30ddb42ea274fa6fe14ba04df608179e044f848 Mon Sep 17 00:00:00 2001 From: dvbcknd <189028215+dvbcknd@users.noreply.github.com> Date: Thu, 9 Jul 2026 03:17:56 -0300 Subject: [PATCH 3/4] =?UTF-8?q?Fix:=20Foi=20feito=20as=20corre=C3=A7=C3=B5?= =?UTF-8?q?es=20que=20foram=20solicitados=20a=20cerca=20do=20nome=20do=20a?= =?UTF-8?q?rquivo=20e=20pasta=20e=20do=20c=C3=B3digo=20de=20exemplo.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../8.8-custom-hooks.md} | 82 ++++++++++--------- 1 file changed, 43 insertions(+), 39 deletions(-) rename docs/{Custom Hooks/custom-hooks.md => Iniciando com React/8.8-custom-hooks.md} (76%) diff --git a/docs/Custom Hooks/custom-hooks.md b/docs/Iniciando com React/8.8-custom-hooks.md similarity index 76% rename from docs/Custom Hooks/custom-hooks.md rename to docs/Iniciando com React/8.8-custom-hooks.md index 47048fb..2c6e85d 100644 --- a/docs/Custom Hooks/custom-hooks.md +++ b/docs/Iniciando com React/8.8-custom-hooks.md @@ -4,7 +4,6 @@

- # **CUSTOM HOOKS: Compartilhando lógica entre componentes** ## O que é um Custom Hook? @@ -41,7 +40,6 @@ ESLint verifiquem se as regras das hooks estão sendo seguidas corretamente. - **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 @@ -53,42 +51,49 @@ os estados de carregamento, erro e dados retornados. import { useState, useEffect } from 'react'; export function useFetch(url){ - const [data, setData] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect( () => { - //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); - if (!response.ok){ - throw new Error("Erro ao buscar a API"); - } - const json = await response.json(); - setData(json); //Guarda os dados. - }catch (err){ - setError(err.message); //Guarda o erro, caso aconteça. - setData(null); - }finally{ - setLoading(false); - } - }; - - if(!url){ - return; - }else{ - fetchData(); //Se tiver URL ele chama a função + 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); } - }, [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 quiser. - return { data, loading, error }; + }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? @@ -100,7 +105,6 @@ os estados de carregamento, erro e dados retornados. - O **`useEffect`** roda automaticamente sempre que a **`url`** mudar, disparando uma nova requisição. - ### Usando a hook em um componente: ```jsx @@ -120,11 +124,11 @@ os estados de carregamento, erro e dados retornados. ); } - ``` - 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 💜

From 447341da3c10bf55551db5f6f766afa5733f5ba5 Mon Sep 17 00:00:00 2001 From: Bruno Gomes <189028215+dvbcknd@users.noreply.github.com> Date: Thu, 9 Jul 2026 03:27:44 -0300 Subject: [PATCH 4/4] Update 8.7-useCallback.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correção do link de direcionamento para o próximo item: 8.8-custom-hooks Signed-off-by: Bruno Gomes <189028215+dvbcknd@users.noreply.github.com> --- docs/Iniciando com React/8.7-useCallback.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)