React  - Consumindo uma Web API com Axios


  Neste artigo vamos consumir uma Web API ASP .NET Core usando o Axios em uma aplicação React.

A ASP .NET Core pode ser usada para criar um backend muito poderoso sendo um dos frameworks com melhor desempenho neste quesito. Combine isso com o poder do React e outras ferramentas como SignalR, Entity Framework, Redux e TypeScript e você será capaz de criar sites incríveis com funcionalidades poderosas que seus clientes irão adorar.

Neste artigo vou mostrar os fundamentos para consumir uma Web API Asp.Net Core usando Axios em uma aplicação React.

A figura abaixo dá uma visão geral das tecnologias que iremos usar para atingir o nosso objetivo:

Apresentando a Web API - ApiProdutos

Eu vou partir de uma Web API pronta que foi criada com a ASP .NET Core 5 usando:

  1. NET 5.0
  2. ASP .NET Core 5.0
  3. EF Core 5.0
  4. SQL Server
  5. VS 2019 Community

É uma API bem simples chamada ApiProdutos que permite gerenciar informações de produtos e que foi criada usando o Scaffolding do VS 2022.

Abaixo temos a execução desta API exibindo os endpoints na interface do Swaqger:

Temos assim uma API pronta para ser consumida atendendo em todos os endpoints que expõe.

Baixe o código da API aqui :   ApiProdutos.zip

Criando o projeto React : Create React App

Vamos agora criar um projeto React usando a ferramenta create-react-app, e, nesta aplicação vamos definir os recursos para consumir a API.

Para criar um projeto usando o Create-React-App basta digitar o comando :

npx create-react-app <nome_do_projeto_react>

O npx vai usar o npm sem você precisar tê-lo instalado e vai criar o projeto React com suas dependências. Ele é o executor de pacotes usado pelo npm para executar pacotes no lugar de uma instalação global. Basicamente, ele cria uma instalação temporária do React para que, a cada novo projeto, você use a versão mais recente do React.

Assim para criar o nosso projeto vamos criar uma pasta, onde vamos armazenar o projeto, e após entrar nesta pasta digitar o comando:  npx create-react-app produtos

Para poder editar o código da aplicação vamos usar o Visual Studio Code (VS Code), e, para abrir o código do projeto basta estar na pasta do projeto e digitar :  code .

Vamos iniciar limpando o projeto criado removendo os seguintes arquivos:

No arquivo App.js vamos remover a linha do import do logo e todo o código a partir da tag <header></header>.

A seguir vamos instalar o Axios e o react-router-dom em nosso projeto abrindo um terminal na janela do editor de código e digitando o comando: 

npm install axios

Com este comando iremos instalar o axios que é um cliente HTTP baseado em promises para o navegador e node.js que iremos usar para acessar a API;

A seguir vamos emitir o comando :  npm install react-router-dom

Com isso instalamos o react-router-dom. Precisamos deste recurso para poder criar as rotas em nossa aplicação React.

Definindo a estrutura do projeto

Vamos criar em nosso projeto dentro da pasta src as pastas pages e services.

A seguir dentro da pasta pages vamos criar as pastas :

  1. assets - Onde vamos incluir a imagem produtos.jpg que iremos exibir;
  2. Inicio  - Onde vamos criar o componente Inicio para apresentar uma imagem e um botão para acessar os produtos;
  3. Produtos - Onde vamos definir o componente Produtos para acessar a API e retornar os produtos;

Teremos assim a seguinte estrutura de pastas no projeto:

Na pasta services vamos criar o arquivo api.js com o seguinte código:

import axios from "axios";
const api = axios.create({
  baseURL: "https://localhost:7090",
});
export default api;

Neste código importamos o Axios da biblioteca axios, criamos a variável chamada api e atribuímos a ela o axios.create, que será o início e a estrutura base do serviço de API que consumiremos. A seguir usamos a propriedade baseURL que recebe o endpoint da nossa aplicação API , ou seja, a URL da API que será acessada.

Ao final exportamos nossa variável api para ser importada em qualquer parte do nosso projeto. Temos assim o serviço do Axios disponível e vamos usá-lo a seguir.

Para não esquecer vamos incluir na pasta assets o arquivo produtos.jpg que iremos usar no componente Inicio.

A seguir vamos criar um arquivo routes.js dentro da pasta src e definir o código abaixo neste arquivo:

import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Produtos from './pages/Produtos';
import Inicio from './pages/Inicio'

export default function Routes(){
    return (
        <BrowserRouter>
         <Switch>
             <Route path="/" exact component={Inicio}/>
             <Route path="/produtos" component={Produtos}/>

         </Switch>
        </BrowserRouter>   
    );
}

No código importamos os recursos BrowserRouter, Reoute e Switch do react-router-dom para podermos definir as rotas.

- BrowserRouter - Todas as rotas precisam estar declaradas dentro desse escopo, ou seja, nenhuma outra rota poderá ser acessada se não tiver sido declarada aqui. Lembrando que há apenas uma declaração de BrowserRouter no projeto.

- Switch - Esse componente é usado quando vamos adicionar várias rotas. Ao declarar o switch, a rota será buscada e, então, quando for encontrada a busca será finalizada Ele garante que não teremos mais de uma rota processada ao mesmo tempo

- Route - Faz renderização da interface, seja um componente ou uma página, quando o caminho (path) combinar com o esperado

Vamos definir duas rotas :

Observe que na rota raiz usamos a palavra exact. Isso é necessário pois o React Router faz uma correspondência parcial para encontrar as rotas e assim como temos '/' e '/produtos' a primeira que ele encontrar com '/' será exibidas.

Usando o exact desativamos essa correspondência parcial para uma rota e garantimos que ela só retorna a rota se o caminho for uma correspondência EXATA para o URL atual.

Agora podemos iniciar criando os componentes.

Criando o componente Inicio

Vamos iniciar criando na pasta Inicio dois arquivos :

  1. index.js   - representa a lógica do componente;
  2. styles.css  - representa os estilos aplicados ao componente;

No arquivo index.js vamos incluir o código a seguir:

import { useHistory } from 'react-router-dom';
import './styles.css'

import ProdutoImage from '../assets/produtos.jpg';

export default function Inicio() {

    const history = useHistory();

    async function iniciar(event) {
        history.push('/produtos');
    }

    return (
        <div className="inicio-container">
            <section className="form">
                <img src={ProdutoImage} alt="produtos" id="img1" class="center" />
                <br/>
                <form onSubmit={iniciar}>
                    <divbutton>
                       <button class="button" type="submit">Ver Produtos</button>
                   </divbutton
>
                </form>
            </section>
        </div>
    )
}

Neste código usamos o hooks useHistory que permite acessar um objeto que representa  o histórico do navegador. Por meio deste objeto de histórico, podemos acessar e manipular o estado atual do histórico do navegador. Assim ele permite acesso a uma instancia da navegação, fazendo com que seja possível acessar outras páginas da aplicação. (Lembrando que o useHistory só pode ser chamado dentro de uma função.)

Criamos a função Iniciar que será acionada quando o usuário clicar no botão - Ver Produtos - acionando o evento OnSubmit do formulário.

No arquivo styles.css inclua o código abaixo:

.inicio-container ul li button {
  position: absolute;
  right: 25px;
  top: 25px;
  border: 0;
  background: transparent;  
}
.center {
    display: block;
    margin-left: auto;
    margin-right: auto;
    width: 50%;
}
divbutton {
  display: flex;
  justify-content: center;
}

Executando a aplicação React com o comando - npm start  - teremos o seguinte resultado.

Vamos a seguir criar o componente Produtos onde vamos acessar a API usando o Axios.

Criando o componente Produtos

Agora, na pasta Produtos crie dois arquivos :

  1. index.js   - representa a lógica do componente;
  2. styles.css  - representa os estilos aplicados ao componente;

No arquivo index.js vamos incluir o código a seguir:

 

import React, { useEffect, useState } from "react";
import api from '../../services/api';
import './styles.css';
export default function Produtos() {
  const [produtos, setProdutos] = useState([]);
  useEffect(() => {
    api.get("/api/produtos/")
       .then((response) => {
         console.log(response);
         setProdutos(response.data)
      })
      .catch((err) => {
        console.error("ops! ocorreu um erro : " + err);
      });
  }, []);
  return (
    <div className="produto-container">
       <h1>Relação de Produtos</h1>
        <ul>
           {produtos.map(produto => (
             <li key={produto.Id}>
                <b>Nome:</b>{produto.nome}<br/>
                <b>Descrição:</b>{produto.descricao}<br/>
                <b>Preço:</b>{produto.preco}<br/>
            </li>
         ))}
        </ul>
    </div>
  );
}

Vamos entender o código:

Iniciamos importando os hooks useEffect e useState, o serviço da api e os estilos.

Assim estamos usando aqui dois hooks do React : useEffect e useState

Os Hooks são uma um novo recurso disponível a partir do React 16.8 que permitem que você use o state e outros recursos do React sem escrever uma classe.

Os hooks permitem o uso de vários recursos de forma simples através de funções. Eles também ajudam a organizar a lógica utilizada dentro dos componentes.

Usamos o hook useEffect para lidar com efeitos colaterais em nossos componentes e vamos usar este hook em nosso projeto para tratar os efeitos colaterais gerados pelos requests Get (Podemos usá-lo também como ciclo de vida do componente)

Nota: Buscar dados, configurar uma subscription, e mudar o DOM manualmente dentro dos componentes React são exemplos de efeitos colaterais.

Para que possamos lidar com as mudanças de estado da nossa aplicação, iremos usar o hook useState.  Ele permite a criação de estado no componente através de função e faz o gerenciamento do estado local do componente e retorna um array como resultado.

O array de retorno possui dois índices: 
const [data, setData]=useState([]);

  1. O primeiro valor deste array é uma variável que guarda o estado em si, que chamamos de data;
  2. O segundo valor é uma variável que é uma função, e é através dela que faremos as atualizações do valor do nosso estado; usamos o nome setData para dar nome a esta função. (O set é uma convenção usada)

Como a nossa função setData é a responsável por alterar o estado de data, precisamos colocá-la dentro do escopo da função useEffect, porque ela é a responsável por pegar os dados que vão modificar o estado da nossa aplicação.

No trecho de código

useEffect(() => {
    api.get("/api/produtos/").then((response) => { console.log(response);
         setProdutos(response.data)
      })
      .catch((err) => {
          console.error("ops! ocorreu um erro : " + err);
      });
  }, []);

Estamos enviando um request get para o endpoint 'api/produtos' da nossa API e a seguir estamos atribuindo os dados retornados ao estado produtos usando setProdutos(response.data)

A seguir estamos mapeando os dados recebidos usando a função map() que é usada para iterar em um array e manipular ou alterar os itens de dados.

  {produtos.map(produto => (
             <li key={produto.Id}>
                <b>Nome:</b>{produto.nome}<br/>
                <b>Descrição:</b>{produto.descricao}<br/>
                <b>Preço:</b>{produto.preco}<br/>
            </li>

Para concluir inclua o código abaixo no arquivo styles.css :

.produto-container {
    width: 100%;
    max-width: 1200px;
    padding: 10 25px;
    margin: 20px auto;
  }

  .produto-container h1 {
    margin-top: 20px;
    margin-bottom: 24px;
    padding-left: 20px;
    color:blue;
  }

  .produto-container ul {
    display: grid;
    padding: 0 25px;
    grid-template-columns: repeat(2, 1fr);
    grid-gap: 35px;
    list-style: none;
  }

 

Com isso podemos abrir um terminal na janela do editor e inicializar a nossa aplicação React digitando : npm start

Iremos visualizar o navegador acessando http://localhost:3000 e exibindo a tabela com os dados da nossa API:

Eu não me preocupei em dar uma formatação mais refinada na exibição dos dados.

Pegue o projeto aqui:  produtos_react.zip (sem as referências)

"Então os justos resplandecerão como o sol, no reino de seu Pai. Quem tem ouvidos para ouvir, ouça."
Mateus 13:43

Referências:


José Carlos Macoratti