Curso de FrontendTutorial5 min de leitura

Integrando o frontend com Axios, Context e .env

Integração de React com backend usando Axios e Context

Integre o frontend React com o backend Node.js usando Axios, Context API e variável de ambiente.

  • #Curso de Frontend
  • #Integração Frontend e Backend
  • #React
  • #Axios
  • #Context
  • #.env
  • #Backend

O que vamos fazer

O frontend deixará de buscar em um JSON local e passará a consumir a rota GET http://localhost:3001/api/search?q=html.

Antes de mexer no React, deixe o backend funcionando e teste http://localhost:3001/api/search?q=html no navegador. A integração só deve começar depois que essa rota responder corretamente.

Instalando Axios e configurando .env

Abra o projeto React no VS Code. No terminal integrado, confirme que você está na pasta do frontend, no mesmo nível do package.json do projeto React, e instale Axios.

Depois, crie um arquivo chamado .env na raiz do projeto frontend. Esse .env fica no frontend, não no backend.

npm install axios

Variável VITE_API_URL

Dentro do .env do frontend, coloque a URL base da API. Como a rota do backend começa com /api, a variável deve terminar em /api.

Depois de criar ou alterar .env no Vite, pare o servidor do frontend e rode npm run dev novamente.

VITE_API_URL=http://localhost:3001/api

Serviço de API

Dentro da pasta src do frontend, crie uma pasta chamada services se ela ainda não existir. Dentro dela, crie o arquivo api.js.

Cole o código abaixo em src/services/api.js. Esse arquivo cria uma instância configurada do Axios para evitar repetir a URL completa em todos os lugares.

Lendo o código: import axios carrega a biblioteca, import.meta.env.VITE_API_URL lê a variável do .env do Vite e axios.create cria uma versão configurada do Axios com baseURL e timeout.

Com baseURL igual a http://localhost:3001/api, uma chamada para api.get('/search') vira uma chamada para http://localhost:3001/api/search.

import axios from "axios";

const apiUrl = import.meta.env.VITE_API_URL;

export const api = axios.create({
  baseURL: apiUrl,
  timeout: 5000
});

Context de busca

Dentro da pasta src do frontend, crie uma pasta chamada contexts se ela ainda não existir. Dentro dela, crie o arquivo SearchContext.jsx.

Esse Context centraliza termo, resultados, mensagem, carregamento e função de busca. Ele também trata erro do Axios, porque respostas 400 e 404 entram no catch.

Lendo os states: term guarda o texto digitado, results guarda os cards retornados, message guarda uma mensagem para a tela e loading indica se a busca ainda está acontecendo.

Lendo a função search: ela normaliza o termo, liga loading, chama a API, salva os resultados no sucesso, trata mensagens de erro no catch e sempre desliga loading no finally.

import { createContext, useContext, useState } from "react";
import { api } from "../services/api";

const SearchContext = createContext(null);

export function SearchProvider({ children }) {
  const [term, setTerm] = useState("");
  const [results, setResults] = useState([]);
  const [message, setMessage] = useState("");
  const [loading, setLoading] = useState(false);

  async function search(searchTerm) {
    const normalizedTerm = String(searchTerm || "").trim();
    setTerm(normalizedTerm);
    setLoading(true);
    setMessage("");

    try {
      const response = await api.get("/search", {
        params: {
          q: normalizedTerm
        }
      });

      setResults(response.data.data || []);
      setMessage(response.data.message || "Resultados encontrados.");
    } catch (error) {
      const responseData = error.response?.data;

      setResults(responseData?.data || []);
      setMessage(responseData?.message || "Não foi possível buscar resultados.");
    } finally {
      setLoading(false);
    }
  }

  return (
    <SearchContext.Provider value={{ term, setTerm, results, message, loading, search }}>
      {children}
    </SearchContext.Provider>
  );
}

export function useSearch() {
  const context = useContext(SearchContext);

  if (!context) {
    throw new Error("useSearch precisa ser usado dentro de SearchProvider");
  }

  return context;
}

Envolvendo a aplicação

Abra o arquivo principal do frontend, normalmente src/main.jsx em projetos Vite com React. Importe SearchProvider e coloque ele ao redor do App.

Se o seu projeto usa src/main.tsx, aplique a mesma ideia nesse arquivo.

Lendo o Provider: SearchProvider fica por fora de App para permitir que qualquer componente interno use useSearch. Sem esse envolvimento, o hook não consegue acessar os dados do Context.

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { SearchProvider } from "./contexts/SearchContext";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <SearchProvider>
      <App />
    </SearchProvider>
  </React.StrictMode>
);

Tela de busca

No componente da tela de busca, importe useSearch de src/contexts/SearchContext.jsx. Use term e setTerm no input, chame search no submit, mostre loading enquanto a requisição estiver em andamento, mostre message para sucesso ou erro e renderize results.

O exemplo abaixo mostra a estrutura mínima. Adapte os nomes das classes e do componente ao projeto que você já criou no frontend.

Lendo o componente: handleSubmit impede o recarregamento da página com event.preventDefault() e chama search(term). O map percorre results e cria um article para cada item retornado pelo backend.

import { useSearch } from "../contexts/SearchContext";

export function SearchPage() {
  const { term, setTerm, results, message, loading, search } = useSearch();

  function handleSubmit(event) {
    event.preventDefault();
    search(term);
  }

  return (
    <section>
      <form onSubmit={handleSubmit}>
        <input
          value={term}
          onChange={(event) => setTerm(event.target.value)}
          placeholder="Buscar por HTML, React ou Node"
        />
        <button type="submit" disabled={loading}>
          {loading ? "Buscando..." : "Buscar"}
        </button>
      </form>

      {message ? <p>{message}</p> : null}

      <div>
        {results.map((item) => (
          <article key={item.id}>
            <h2>{item.title}</h2>
            <p>{item.description}</p>
            <a href={item.url} target="_blank" rel="noreferrer">
              Abrir referência
            </a>
          </article>
        ))}
      </div>
    </section>
  );
}

Testando a integração

Rode o backend e o frontend ao mesmo tempo, cada um em seu próprio terminal. Deixe os dois terminais abertos.

No navegador, abra a URL do frontend mostrada pelo Vite, normalmente http://localhost:5173. Pesquise por html, react, node e sql para conferir o fluxo completo.

Se o backend responder no navegador, mas o frontend não mostrar dados, confira VITE_API_URL no .env do frontend, reinicie o Vite e veja se CORS_ORIGIN no .env do backend está apontando para a URL correta do frontend.

cd ~/Desktop/curso-frontend/backend-node
npm run dev

cd ~/Desktop/curso-frontend/projeto-react
npm run dev

Compartilhar

Voltar ao blog
Avatar 3D de argila do Close Luca
Sobre o autor45 artigos publicados

Luca

Desenvolvedor de software

Desenvolvedor de software, criador de projetos web e entusiasta de game design. Escreve sobre programação, desenvolvimento de jogos, produtividade e tecnologia aplicada a produtos digitais.

Compre pelo link do canal
Continue lendo
Ver todos os artigos
React Context com Provider e useContext
Curso de Frontend3 min

Context no React: o que é, como funciona e quando usar

Entenda o que é Context no React, como funciona com Provider e useContext, quando usar e quando evitar.

Ler artigo
Arquivos .env e .gitignore em projetos frontend e backend
Curso de Frontend3 min

.env e .gitignore: segurança e organização

Entenda o que é .env, por que variáveis de ambiente são importantes e como usar .gitignore.

Ler artigo
Configuração inicial de backend Node.js
Curso de Frontend4 min

Criando o repositório backend-node e instalando o projeto

Crie o repositório backend-node, inicialize o projeto com npm init e instale as dependências principais.

Ler artigo