I have a project where I use Next.js on the front-end and Express.js on the back.
Front-end side The ‘pages’ file contains ‘index.js’. In it, I am sending the following request.
import Home from "./home/home"; import axios from "axios"; import { useState } from "react"; export default function Index({ data }) { const [products, setProducts] = useState(data); const [start, setStart] = useState(1); const getMoreProducts = async () => { setStart(start + 1); const { newProducts } = await axios.get( `${process.env.NEXT_PUBLIC_BACK_END}/test` ); setProducts([...products, ...newProducts]); }; return ( <div> <Home data={products} /> <button onClick={getMoreProducts}> Load more {start}</button> </div> ); } export async function getServerSideProps(context) { // Fetch data from external API const { data } = await axios.get( `${process.env.NEXT_PUBLIC_BACK_END}/productlist/pagination`, { params: { page: 1, limit: 5, }, } ); return { props: { data: data || {}, }, }; // Pass data to the page via props }
Back-end side
const express = require("express"); var cors = require('cors') const app = express(); require("dotenv").config(); const mongoose = require("mongoose"); mongoose.connect( "*********", { useNewUrlParser: true } ); const db = mongoose.connection; db.on("error", (err) => console.error(err)); db.once("open", () => console.log("Connected to Database ")); app.use(express.json()); const productlistRouter = require("./routes/productlist"); const test = require("./routes/test"); app.use("/productlist", productlistRouter); app.use("/test", test); app.use(cors()) app.listen(3000, () => console.log("Server is running"));
And here is my Route code :
const express = require("express"); const router = express.Router(); const Product = require("../models/product"); const cors = require("cors"); const corsOptions = { headers: [ { key: "Access-Control-Allow-Credentials", value: "true" }, { key: "Access-Control-Allow-Origin", value: "*" }, // ... ], origin: "*", optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204 }; router.get("/showall", async (req, res) => { try { const product = await Product.find(); res.json(product); } catch (err) { res.status(500).json({ message: err.message }); } }); router.get("/pagination", cors(corsOptions), async (req, res) => { const page = req.query.page; const limit = req.query.limit; const startIndex = (page - 1) * limit; const endIndex = page * limit; const products = await Product.find(); const result = products.slice(startIndex, endIndex); res.json(result); });
So, When the page is first built with Next.js, the api works, but when I click the ‘Load more’ button, it gives a CORS error. When I use the same query with ‘postman’ and other tools, it does not give any error. On the Next.js side, it works when I send a query to another 3rd party API., but it doesn’t work when I send it to my own back-end. And no matter what page or component I do this in, only the APIs that are created at the build time are working.
What could be the reason for this? and how can i solve it? I’ve read and searched a few articles about cors, but I still haven’t found a solution for days.
Advertisement
Answer
CORS should be placed on top level as javascript is executed one by one line. Place app.use(cors())
just above the line of app.use("/productlist", productlistRouter);