Rotas de API
As rotas de API permitem que você crie APIs com Next.js.
Se você abrir pages/api/hello.js
verá o seguinte:
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
Inicie o servidor de desenvolvimento Next.js com:
npm run dev
Então abra http://localhost:3000/api/hello no seu navegador. Você deve ver o seguinte:
Como temos um arquivo chamado hello.js
dentro do pages/api
Next.js, criaremos uma rota para esta API em /api/hello
. Rotas de API também podem ser dinâmicas , assim como páginas dinâmicas que abordamos na lição anterior. Abordaremos como criar rotas de API dinâmicas mais adiante neste artigo.
Detalhamento do código
Vamos dar uma olhada mais aprofundada no hello.js
arquivo.
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
Este arquivo contém uma única função exportada chamada handler()
. O nome desta função não é importante, você pode nomeá-la como quiser, mas handler é uma convenção comum. A função tem dois parâmetros req
e res
.
- O
req
parâmetro é uma instância de http.IncomingMessage do Node.js - O
res
parâmetro é uma instância de http.ServerResponse do Node.js
O Next.js também fornece alguns middlewares e funções auxiliares integrados para facilitar o trabalho com os objetos de solicitação e resposta.
O corpo da nossa handler()
função contém o seguinte:
res.status(200).json({ name: 'John Doe' })
Isso retorna um código de status de resposta de 200 e, em seguida, retorna um objeto JSON com uma propriedade de nome e “John Doe” como seu valor.
Métodos de solicitação HTTP
Nosso método handler responderá atualmente a qualquer método de solicitação HTTP, mas e se quisermos ter respostas diferentes para solicitações diferentes? Podemos fazer isso detectando qual tipo de método HTTP nossa rota de API está recebendo usando o req
objeto.
Vamos atualizar nossa handler()
função para responder apenas a solicitações HTTP Get.
export default function handler(req, res) {
if (req.method === 'GET') {
res.status(200).json({ name: 'John Doe' })
}
}
Usando uma if()
declaração simples, podemos detectar diferentes métodos de solicitação HTTP que nossa rota de API recebe e responder adequadamente.
Vamos atualizar nosso handler()
para lançar um código de status 400 se ele receber qualquer método HTTP diferente de GET.
export default function handler(req, res) {
if (req.method === 'GET') {
res.status(200).json({ name: 'John Doe' })
} else {
res.status(400).json({ error: 'Your request could not be processed.' })
}
}
Rotas de API e getStaticProps
Agora que temos um melhor entendimento das rotas de API, vamos ver como podemos usá-las dentro das páginas Next.js. Dentro delas, pages/posts/[id].js
estamos fazendo uma chamada de API para uma API externa para obter nossos dados de postagem.
export async function getStaticProps({ params }) {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts/${params.id}`
)
const post = await res.json()
console.log(post)
return { props: { post } }
}
Vamos criar uma nova rota de API para nossas postagens e usá-la dentro da getStaticProps()
função.
Rota da API de postagens
Primeiro, crie um novo arquivo chamado posts.js
dentro de /pages/api
algo assim.
Em seguida, criaremos nossa handler()
função.
export default function handler(req, res) {}
Em seguida, precisaremos retornar os dados de nossos posts. Para fazer isso, copiaremos o JSON de https://jsonplaceholder.typicode.com/posts para um novo arquivo e o usaremos dentro do nosso handler()
.
Crie uma nova pasta chamada data
na raiz do nosso projeto Next.js. Então crie um arquivo chamado posts.json
dentro dela.
Copie e cole todas as postagens de https://jsonplaceholder.typicode.com/posts no posts.json
arquivo.
Em seguida, precisaremos importar esse arquivo para o nosso pages/api/posts.js
arquivo assim:
import posts from '../../data/posts.json'
export default function handler(req, res) {}
Agora tudo o que precisamos fazer é retornar nossas postagens da nossa handler()
função assim:
import posts from '../../data/posts.json'
export default function handler(req, res) {
res.status(200).json(posts)
}
Agora, se você acessar a URL http://localhost:3000/api/posts no seu navegador, verá o seguinte:
Agora que nossa rota de API retorna nossas postagens, precisamos atualizar as funções getStaticProps()
e getStaticPaths()
para nossa rota de API assim:
Aqui está todo o conteúdo depages/posts/[id].js
function Post({ post }) {
return (
<>
<h1>{post.title}</h1>
<p>{post.body}</p>
</>
)
}
export async function getStaticPaths() {
const res = await fetch('http://localhost:3000/api/posts')
const posts = await res.json()
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}))
return { paths, fallback: false }
}
export async function getStaticProps({ params }) {
const res = await fetch(`http://localhost:3000/api/posts/${params.id}`)
const post = await res.json()
console.log(post)
return { props: { post } }
}
export default Post
Você deve receber um erro.
Vamos tentar obter uma de nossas postagens visitando http://localhost:3000/posts/1 você deverá ver o seguinte erro:
Então o que exatamente está acontecendo aqui? Bem, se você olhar de perto, dentro de getStaticProps()
nós estamos tentando buscar cada post por um número de ID:
const res = await fetch(`http://localhost:3000/api/posts/${params.id}`)
O problema é que criamos apenas uma rota de API para, /api/posts
não para /api/posts/1
. Para que isso funcione, precisamos criar uma rota de API dinâmica .
Rotas de API dinâmicas
Crie uma pasta chamada posts
dentro de /pages/api
algo assim:
Em seguida, vá /pages/api/posts.js
para dentro da /pages/api/posts
pasta e renomeie-a paraindex.js
Agora crie um arquivo com o /api/posts/[id].js
seguinte nome:
Em seguida, copie e cole o seguinte em pages/api/[id].js
.
import posts from '../../../data/posts.json'
export default function handler(req, res) {
res.status(200).json(posts)
}
Agora, se você acessar a URL http://localhost:3000/api/posts/1, verá o seguinte:
Nossa rota de API dinâmica está retornando todos os dados das postagens em vez de apenas uma única postagem com o ID 1. Vamos escrever alguma lógica dentro da nossa handler()
função para filtrar esses dados e retornar a postagem correta com base no ID na URL.
A primeira coisa que precisamos fazer é obter o número de identificação da solicitação.
export default function handler(req, res) {
const { id } = req.query
res.status(200).json(posts)
}
Estamos usando a desestruturação para obter o ID do objeto de solicitação.
const { id } = req.query
Podemos verificar isso passando a id
variável para o nosso res
assim:
export default function handler(req, res) {
const { id } = req.query
res.status(200).json(id)
}
Agora, se você visitar http://localhost:3000/api/posts/1, deverá ver o seguinte:
Agora que estamos obtendo o ID da resposta, podemos usá-lo para filtrar todos os dados das postagens e retornar a postagem com o ID correto.
export default function handler(req, res) {
const { id } = req.query
const post = posts.filter((post) => id == post.id)
res.status(200).json(post)
}
Agora, quando visitarmos http://localhost:3000/api/posts/1, veremos apenas os dados da postagem para esse ID.
Cada vez que você alterar o ID na URL, você deverá receber uma postagem diferente.
Agora, se você tentar visitar http://localhost:3000/posts/1, você notará que a tela está em branco!?! Se você olhar atentamente para os dados JSON retornados de cada post, verá que os dados do post estão aninhados dentro de um array.
Dentro pages/posts/[id].js
do topo do nosso arquivo, nossa Post
função é a seguinte:
function Post({ post }) {
return (
<>
<h1>{post.title}</h1>
<p>{post.body}</p>
</>
)
}
Não esperamos que os dados sejam aninhados dentro de um array, e é por isso que o post não está sendo exibido. Temos duas opções para consertar isso.
A primeira opção é atualizar Post()
assim:
function Post({ post }) {
console.log(post)
return (
<>
<h1>{post[0].title}</h1>
<p>{post[0].body}</p>
</>
)
}
A segunda opção e melhor opção na minha opinião é usar a desestruturação novamente. Atualize getStaticProps()
para o seguinte:
function Post({ post }) {
console.log(post)
return (
<>
<h1>{post.title}</h1>
<p>{post.body}</p>
</>
)
}
// ...
export async function getStaticProps({ params }) {
const res = await fetch(`http://localhost:3000/api/posts/${params.id}`)
const [post] = await res.json() // this is destructuring
return { props: { post } }
}
<aside> 💡 Observe que não precisamos atualizar nada na Post
função no topo, pois agora estamos enviando os dados corretos.
</à parte>
Nesta linha aqui:
const [post] = await res.json()
estamos desestruturando o objeto post do array em que ele está aninhado.
Encerrar
Neste artigo você aprendeu o seguinte:
- Como criar rotas de API em Next.js
- Como responder a diferentes métodos e solicitações HTTP
- Como usar rotas de API dentro de páginas Next.js
- Como criar rotas de API dinâmicas
Nenhum comentário:
Postar um comentário