Skip to content
← Voltar para o Skalablog

Artigo publicado

Implementando Autocomplete com Next.js e Google Maps

Neste artigo, mostramos em detalhes como criar um componente de autocomplete de endereços em um app feito com Next.js, integrado com a API do Google Maps, conforme demonstrado neste vídeo. Esta solução permite ao usuário digitar endereços de origem e destino, receber sugestões instantâneas e salvar a rota, com várias dicas práticas de integração e UX.

Objetivo do projeto

O foco é entregar uma tela funcional onde usuários digitam o endereço de origem e destino em campos de texto, com sugestões que aparecem de acordo com o que está sendo digitado. Ao selecionar uma sugestão, os campos são preenchidos de forma automática e o valor do endereço é armazenado para uso posterior, como salvar itinerários ou buscar direções.

Setup: bibliotecas e configuração inicial

O projeto utiliza Next.js para front-end, React Hook Form para controle de formulários, Yup para validação, Downshift para o mecanismo de autocomplete, Chakra UI na estilização e react-highlight-words para destacar os termos buscados nas sugestões. Todas essas dependências podem ser instaladas com:

yarn add react-hook-form yup @hookform/resolvers downshift chakra-ui/react react-highlight-words

Recomenda-se já criar um arquivo de ambiente (.env.local) com a variável NEXT_PUBLIC_API_URL definida apontando para a URL base da sua API.

Componentização e arquitetura do autocomplete

O componente principal de autocomplete, implementado geralmente como Autocomplete.tsx, recebe vários props essenciais: a lista de candidatos a exibir, funções para customização de renderização do input e itens, além de estilos customizáveis. Para maximizar a flexibilidade, a interface de cada item da lista deve conter ao menos:

  • label: nome visível do local
  • value: ID do local (normalmente o Place ID retornado pelo Google Maps)

Exemplo de interface:

interface Item {
  label: string;
  value: string;
}

A função de filtro de sugestões faz buscas com base na string do usuário, comparando (com .includes(), case insensitive) cada chave relevante de cada item:

function defaultOptionsFilter(items: Item[], inputValue: string): Item[] {
  return items.filter(item =>
    item.label.toLowerCase().includes(inputValue.toLowerCase())
  );
}

Integração com o Google Maps API (backend e frontend)

O grande destaque é a integração API: quando o usuário começa a digitar, é feita uma requisição para o backend do próprio projeto (API Route Next.js), que se comunica com o Google Maps Places API e devolve sugestões de endereços. Esse fluxo evita expor sua chave da API do Google ao usuário final e centraliza o tratamento de erros.

Exemplo resumido do endpoint Next.js:

// pages/api/places.ts
import { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { text } = req.query;
  try {
    const googleRes = await fetch(`https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${text}&key=${process.env.GOOGLE_MAPS_API_KEY}`);
    const data = await googleRes.json();
    // Mapeia para o formato usado pelo autocomplete
    const candidates = data.predictions.map(p => ({ label: p.description, value: p.place_id }));
    res.status(200).json({ candidates });
  } catch (err) {
    res.status(500).json({ candidates: [] });
  }
}

No frontend, um hook useEffect observa as mudanças do input e chama a função de busca, recebendo a lista pronta de sugestões. Um debounce de 1,5 segundo (1500ms) é implementado via setTimeout para evitar excesso de requisições à API:

useEffect(() => {
  if (!inputValue) return;
  const timeoutId = setTimeout(() => {
    fetch(`/api/places?text=${inputValue}`)
      .then(res => res.json())
      .then(data => setSuggestions(data.candidates));
  }, 1500);
  return () => clearTimeout(timeoutId);
}, [inputValue]);

Renderização de sugestões, seleção e destaques

O autocomplete exibe as sugestões em um dropdown abaixo do input, estilizado com Chakra UI. Ao navegar usando teclado ou mouse, a sugestão em destaque recebe uma cor diferenciada (exemplo: purple.700 de fundo, texto branco) facilitando a visualização do item selecionado.

Para melhorar a UX, termos digitados pelo usuário aparecem destacados nas sugestões usando react-highlight-words:

<Highlighter
  highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
  searchWords={[inputValue]}
  autoEscape
  textToHighlight={item.label}
/>

Todos os eventos principais (mudança de texto, seleção de sugestão com clique ou Enter/Tab, navegação com setas) são tratados e as funções apropriadas são chamadas para garantir acessibilidade e sincronização dos campos e estados internos do formulário.

Lidando com rotas e IDs salvos

Além de salvar apenas os textos digitados, o sistema guarda também os Place IDs correspondentes aos endereços escolhidos. Isso permite futura exibição de mapas, rotas e distâncias, e elimina a necessidade de o usuário saber o ID manualmente.

A integração é feita observando os valores dos campos de origem e destino via watch do React Hook Form, realizando buscas eficientes pelo Place ID através do Array de candidatos salvo, sempre comparando pelo label selecionado:

const currentOrigin = originListPlaces.find(item => item.label === watch('originText'));
const currentDestination = destinationListPlaces.find(item => item.label === watch('destinationText'));
const sourceId = currentOrigin?.value;
const destinationId = currentDestination?.value;

Otimizações e futuras melhorias

  • Exibir um loading (indicador de carregamento) no dropdown enquanto a API responde.
  • Exibir um mapa, usando a seleção de origem/destino, com direções detalhadas entre eles.
  • Refatorar a duplicação de código que observa os campos (origin/destination), unificando em uma função customizada.
  • Valarmos as cores e acessibilidade do dropdown, pensando em contraste e usabilidade.

Exemplos de usos e endereços reais

O sistema completo pode ser usado para encontrar e cadastrar rotas entre pontos reais como:

  • Center Shopping
  • Pratic Shopping
  • Deus Uberlândia Shopping
  • Rua Prudente Morais
  • Rua das Flores
  • Rua dos Carneiros

Utilizar Place IDs dessas localidades permite posteriormente reutilizar os dados e integrar facilmente à exibição de mapas no próprio app ou exportação para sistemas externos.

Considerações finais: desafios práticos e próximos passos

O autocomplete de endereços via Google Maps integrado ao Next.js e React Hook Form oferece uma base poderosa para apps de navegação urbana, delivery, logística e muito mais. Cada aspecto do código foi pensado para permitir expansão: seja adicionando mapas em tempo real, seja integrando funcionalidades de backend mais complexas.

O próximo passo sugerido é justamente adicionar mapas à tela de cadastro, mostrando rotas e distâncias em tempo real assim que endereços são selecionados. Isso melhorará ainda mais a experiência do usuário e trará funcionalidades bastante procuradas em apps modernos de localização.


Veja o vídeo original do projeto para referência e demonstração

YouTube thumbnail: Nunca foi tão fácil fazer um AUTOCOMPLETE do Google Maps

Source video

Nunca foi tão fácil fazer um AUTOCOMPLETE do Google Maps

Create from this video

This article was created automatically from a new video.

Automate my channel

Turn your YouTube videos into articles

Built for creators with a backlog and no editor on staff. This page started as a video — Skalablog drafts from the transcript, you review every word, then publish on a first-party /p/{slug} page. Nothing goes live until you publish it.

Turn your videos into articles

Published with Skalablog