Reputation: 789
I just got into Next.js and I cannot figure out how to connect my next.js app with my express api. I was able to make it work but I'm pretty sure this is not the right way to implement it since in my Index component I hard coded the fetch url and I know that in production if the port is not the same it won't work.
I tried to put only the route and the fetch API doesn't allow me to do so.
My index page looks like so
import Link from "next/link";
import fetch from "isomorphic-unfetch";
const Index = props => (
<>
<h1>Youtubers</h1>
<ul>
{props.youtubers.map(youtuber => (
<li key={youtuber._id}>
<Link as={`/p/${youtuber._id}`} href={`/post?id=${youtuber.id}`}>
<a>{youtuber.name}</a>
</Link>
</li>
))}
</ul>
</>
);
Index.getInitialProps = async function() {
// this url I think is wrong ↓
const res = await fetch("https://localhost:5000/youtuber");
const data = await res.json();
return {
youtubers: data.youtubers
};
};
export default Index;
And in my server.js I have this inside the app.prepare().then()
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());
mongoose.connect(process.env.MONGODB_PASSWORD, {
useNewUrlParser: true,
useCreateIndex: true
});
mongoose.connection.on("open", function() {
console.log("mongodb is connected!!");
});
mongoose.connection.on(
"error",
console.error.bind(console, "MongoDB connection error:")
);
//CORS handler
server.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
if (req.method === "OPTIONS") {
res.header(
"Access-Control-Allow-Methods",
"PUT, POST, PATCH, DELETE, GET"
);
return res.status(200).json({});
}
next();
});
//Question Route
server.use("/youtuber", youtuberRoutes);
server.get("*", (req, res) => {
return handle(req, res);
});
server.listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
Upvotes: 0
Views: 1921
Reputation: 2900
which Nextjs version do you use? if it's v9, you can use this https://nextjs.org/docs#api-middlewares to provide your end-point.
Hope to help you.
@Jonney Shih you can create HOC and use it like this:
import mongoose from 'mongoose'
const withConnect = handler => async (req, res) => {
if (!mongoose.connection.readyState) {
const uri = 'mongodb+srv://YOUR-CONNECTION'
await mongoose.connect(uri, {
useNewUrlParser: true,
autoIndex: false
})
}
return handler(req, res)
}
export default withConnect
and use it in pages/api/YOUR-ENDPOINT-HERE
import withConnect from '../../../../hoc/withConnect'
import YOUR-SCHEMA from '../../../../models/SCHEMA-NAME.schema'
const handler = async (req, res) => {
// check req method
if (req.method === 'POST') {
// Use your schema here e.g:
const users = await User.find().exec()
return SOMETHING
}
return SOMETHING
}
export default withConnect(handler)
NOTE: Maybe you need to check model exist like this:
const User: IUserModel = models.User || model('User', userSchema)
Have fun
Upvotes: 1
Reputation: 158
I was able to make it work but I'm pretty sure this is not the right way to implement it since in my Index component I hard coded the fetch url and I know that in production if the port is not the same it won't work.
To make the url dynamic so it works in dev and production, you can capture the full url in _app.js getInitialProps and then pass that into your index component's getInitialProps for use.
_app.js
import get from 'lodash/get';
...
static async getInitialProps({ Component, ctx }) {
const serverUrl = ctx.req ? `${ctx.req.protocol}://${ctx.req.get('Host')}` : '';
...
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps({ serverUrl });
}
return { pageProps };
}
...
index.js
...
static async getInitialProps({ serverUrl }) {
const res = await fetch((`${serverUrl}/youtuber`);
...
Upvotes: 0