> For the complete documentation index, see [llms.txt](https://salvatore-academy.gitbook.io/dev-fullstack-web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://salvatore-academy.gitbook.io/dev-fullstack-web/academia/missoes-de-frontend/conectando-com-apis-backend.md).

# Conectando com APIs Backend

{% hint style="info" %}
Esta missão ensina como as aplicações React interagem com APIs backend. Aprenderemos a usar a Fetch API para fazer requisições HTTP, gerenciar o estado e os efeitos colaterais com hooks do React, e construir um componente interativo que consome uma API, processando respostas e lidando com erros de forma eficaz.
{% endhint %}

## Vídeo

{% embed url="<https://youtu.be/hTncMAFn0ns>" %}

**Link direto:** <https://youtu.be/hTncMAFn0ns>

## Tópicos

1. **Introdução às APIs e Uso da Fetch API:**
   * Discussão sobre o papel das APIs na comunicação entre frontend e backend.
   * Como usar a Fetch API para realizar requisições GET e POST para um servidor backend.
2. **Hooks para Gerenciamento de Estado e Efeitos:**
   * Detalhes sobre como utilizar os hooks `useState` e `useEffect` para gerenciar o estado e lidar com efeitos colaterais em React.
   * Exemplos práticos de como esses hooks são essenciais para interações dinâmicas com APIs.
3. **Manipulação de Respostas e Tratamento de Erros:**
   * Técnicas para manipular respostas de API e realizar tratamento adequado de erros.
   * Estratégias para garantir que a aplicação se comporte de maneira robusta em cenários de erro.
4. **Construção de um Componente Interativo:**
   * Implementação de um componente que faz requisições a uma API e exibe dados.
   * Inclusão de funcionalidades interativas, permitindo aos usuários enviar dados para o backend e receber respostas que alteram a UI.

## Material de Apoio

### Repositório no GitHub

{% embed url="<https://github.com/SalvatoreAcademy/frontend-missao-aprendizado-iniciante-conectando-com-apis-backend>" %}

### PDF para Download

{% file src="/files/G1K2chO5jXGAT6frW5rF" %}

### Miro

{% embed url="<https://miro.com/app/board/uXjVNOBw03o=/?moveToWidget=3458764587893333706&cot=14>" %}

## Exercícios de Fixação

{% hint style="info" %}
Use esses exercícios para reforçar o que acabou de aprender. Se errar, leia a explicação para entender melhor o conceito.
{% endhint %}

<details>

<summary>Qual é a função principal da Fetch API no desenvolvimento web?</summary>

A) Instalar pacotes npm automaticamente.

B) Facilitar a comunicação entre o frontend e o backend através de requisições HTTP.

C) Criar componentes React.

D) Inicializar um novo projeto NodeJS.

</details>

<details>

<summary>Resposta correta</summary>

**Qual é a função principal da Fetch API no desenvolvimento web?**

**Resposta Correta**: B

**Feedback**: A Fetch API facilita a comunicação entre o frontend e o backend através de requisições HTTP, permitindo que os dados sejam enviados e recebidos de um servidor.

</details>

***

<details>

<summary>Complete o código para realizar uma requisição GET usando a Fetch API.</summary>

{% code lineNumbers="true" %}

```javascript
async function fetchData() {
  try {
    const response = await fetch('https://api.exemplo.com/data');
    const data = await response.________();
    console.log(data);
  } catch (error) {
    console.error('Erro:', error);
  }
}

fetchData();
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

**Complete o código para realizar uma requisição GET usando a Fetch API.**

**Resposta Correta**: `json`

**Feedback**: O método `response.json()` é usado para converter a resposta da Fetch API em um objeto JavaScript.

</details>

***

<details>

<summary>Verdadeiro ou Falso: O hook useState do React é utilizado para gerenciar efeitos colaterais.</summary>

A) Verdadeiro

B) Falso

</details>

<details>

<summary>Resposta correta</summary>

**Verdadeiro ou Falso: O hook useState do React é utilizado para gerenciar efeitos colaterais.**

**Resposta Correta**: B

**Feedback**: Falso. O hook `useState` é usado para gerenciar o estado dos componentes React, enquanto o hook `useEffect` é usado para gerenciar efeitos colaterais.

</details>

***

<details>

<summary>Complete o código para configurar um endpoint que responde com uma lista de personagens.</summary>

{% code lineNumbers="true" %}

```javascript
export const Api = {
  baseUrl: 'https://backend-iniciante-integrar-com-frontend.onrender.com/',

  personagem: {
    endpoint: function () {
      return Api.baseUrl + 'personagem'
    },
    readAll: function () {
      return this.endpoint() + '/'
    }
  },

  buildApiGetRequest: function (url) {
    return _________(url, { method: 'GET' }).catch(function (error) {
      console.error('Erro ao carregar dados: ' + url, error)
      toast.error('Erro ao carregar dados.')
    })
  }
}
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

**Complete o código para configurar um endpoint que responde com uma lista de personagens.**

**Resposta Correta**: `fetch`

**Feedback**: O método `fetch` da biblioteca fetch é usado para realizar uma requisição.

</details>

## Exercícios de Validação

{% hint style="info" %}
Esses exercícios testarão sua compreensão prática. Revise o feedback para melhorar suas habilidades.
{% endhint %}

### Desafio de Código

Crie um componente React que busque dados de uma API e exiba uma lista de personagens. O componente deve:

1. Utilizar a Fetch API para buscar dados.
2. Gerenciar o estado dos dados usando `useState`.
3. Utilizar `useEffect` para realizar a busca de dados quando o componente for montado.
4. Exibir os dados na interface do usuário.

<details>

<summary>Resposta esperada</summary>

{% code lineNumbers="true" %}

```jsx
import React, { useState, useEffect } from 'react';
import { Api } from './api';

export default function Personagens() {
  const [personagens, setPersonagens] = useState([]);

  useEffect(function () {
    async function fetchData() {
      try {
        const response = await Api.buildApiGetRequest(Api.personagem.readAll());
        const data = await response.json();
        setPersonagens(data);
      } catch (error) {
        console.error('Erro ao buscar dados:', error);
      }
    }

    fetchData();
  }, []);

  return (
    <div>
      <h1>Lista de Personagens</h1>
      <ul>
        {personagens.map(function (personagem) {
          return <li key={personagem._id}>{personagem.nome}</li>;
        })}
      </ul>
    </div>
  );
}
```

{% endcode %}

**Feedback**: Certifique-se de que o componente está utilizando `useState` para gerenciar o estado dos personagens e `useEffect` para buscar os dados da API quando o componente for montado. A lista de personagens deve ser exibida na interface do usuário.

</details>

### Revisão de Código

{% hint style="danger" %}
**Analise o código a seguir, encontre e corrija o erro.**
{% endhint %}

{% code lineNumbers="true" %}

```jsx
import React, { useState, useEffect } from 'react';
import { Api } from './api';

export default function Personagens() {
  const [personagens, setPersonagens] = useState([]);

  useEffect(function () {
    async function fetchData() {
      try {
        const response = await Api.buildApiGetRequest(Api.personagem.readAll());
        const data = await response.json();
        setPersonagens(data);
      } catch (error) {
        console.error('Erro ao buscar dados:', error);
      }
    }

    fetchData();
  }, [personagens]);

  return (
    <div>
      <h1>Lista de Personagens</h1>
      <ul>
        {personagens.map(function (personagem) {
          return <li key={personagem._id}>{personagem.nome}</li>;
        })}
      </ul>
    </div>
  );
}
```

{% endcode %}

<details>

<summary>Resposta Correta</summary>

**Erro:** O array de dependências no `useEffect` está incorreto. Deve ser um array vazio para que a busca de dados ocorra apenas uma vez quando o componente for montado.

{% code lineNumbers="true" %}

```jsx
useEffect(function () {
  async function fetchData() {
    try {
      const response = await Api.buildApiGetRequest(Api.personagem.readAll());
      const data = await response.json();
      setPersonagens(data);
    } catch (error) {
      console.error('Erro ao buscar dados:', error);
    }
  }

  fetchData();
}, []); // Correção: array de dependências vazio
```

{% endcode %}

**Feedback**: Certifique-se de que o array de dependências do `useEffect` está correto para evitar chamadas infinitas à API.

</details>

### Projeto Prático

Crie uma aplicação React que inclua:

1. Um componente que busque dados de uma API e exiba uma lista de itens.
2. Funcionalidade para deletar itens da lista através de uma requisição DELETE.
3. Tratamento de erros e exibição de mensagens de erro usando react-toastify.

#### Tarefas

1. **Configuração Inicial**:
   * Inicialize um novo projeto React.
   * Instale as dependências necessárias, incluindo react-toastify.
2. **Implementação dos Endpoints no api.js**:
   * Implemente funções para realizar requisições GET e DELETE.
3. **Criação do Componente React**:
   * Crie um componente que faça uso das funções do `api.js` para buscar e deletar itens da lista.
   * Utilize react-toastify para tratar e exibir erros.

<details>

<summary>Código esperado</summary>

{% code title="api.js" lineNumbers="true" %}

```javascript
export const Api = {
  baseUrl: 'https://backend-iniciante-integrar-com-frontend.onrender.com/',

  personagem: {
    endpoint: function () {
      return Api.baseUrl + 'personagem'
    },
    readAll: async function () {
      try {
        const response = await fetch(this.endpoint(), { method: 'GET' });
        return await response.json();
      } catch (error) {
        console.error('Erro ao carregar dados: ' + this.endpoint(), error);
        throw error;
      }
    },
    delete: async function (id) {
      try {
        const response = await fetch(this.endpoint() + '/' + id, { method: 'DELETE' });
        if (!response.ok) {
          throw new Error('Erro ao deletar item');
        }
      } catch (error) {
        console.error('Erro ao deletar dados: ' + this.endpoint() + '/' + id, error);
        throw error;
      }
    }
  }
};

```

{% endcode %}

{% code title="App.jsx" lineNumbers="true" %}

```jsx
import React, { useState, useEffect } from 'react';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { Api } from './api';

export default function App() {
  const [items, setItems] = useState([]);

  useEffect(function () {
    async function fetchData() {
      try {
        const data = await Api.personagem.readAll();
        setItems(data);
      } catch (error) {
        toast.error('Erro ao buscar dados');
        console.error('Erro ao buscar dados:', error);
      }
    }

    fetchData();
  }, []);

  const deleteItem = async function (id) {
    try {
      await Api.personagem.delete(id);
      setItems(items.filter(item => item._id !== id));
    } catch (error) {
      toast.error('Erro ao deletar item');
      console.error('Erro ao deletar item:', error);
    }
  };

  return (
    <div>
      <h1>Lista de Itens</h1>
      <ul>
        {items.map(function (item) {
          return (
            <li key={item._id}>
              {item.nome}
              <button onClick={function () { deleteItem(item._id); }}>Deletar</button>
            </li>
          );
        })}
      </ul>
      <ToastContainer />
    </div>
  );
}
```

{% endcode %}

**Feedback Detalhado**

* **Verificação dos Endpoints**: Certifique-se de testar cada rota (`GET` para buscar itens e `DELETE` para deletar itens) e verificar as respostas.
* **Tratamento de Erros**: Utilize o `toast.error` para exibir mensagens de erro em caso de falhas nas requisições.
* **Estrutura**: A aplicação deve utilizar `useState` para gerenciar o estado dos itens e `useEffect` para buscar dados da API quando o componente for montado.

</details>
