I’m new to Next.js and I’m trying to understand the suggested structure and dealing with data between pages or components.
For instance, inside my page home.js
, I fetch an internal API called /api/user.js
which returns some user data from MongoDB. I am doing this by using fetch()
to call the API route from within getServerSideProps()
, which passes various props to the page after some calculations.
From my understanding, this is good for SEO, since props get fetched/modified server-side and the page gets them ready to render. But then I read in the Next.js documentation that you should not use fetch()
to all an API route in getServerSideProps()
. So what am I suppose to do to comply to good practice and good SEO?
The reason I’m not doing the required calculations for home.js
in the API route itself is that I need more generic data from this API route, as I will use it in other pages as well.
I also have to consider caching, which client-side is very straightforward using SWR to fetch an internal API, but server-side I’m not yet sure how to achieve it.
home.js
:
export default function Page({ prop1, prop2, prop3 }) {
// render etc.
}
export async function getServerSideProps(context) {
const session = await getSession(context)
let data = null
var aArray = [], bArray = [], cArray = []
const { db } = await connectToDatabase()
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
if (session) {
const hostname = process.env.NEXT_PUBLIC_SITE_URL
const options = { headers: { cookie: context.req.headers.cookie } }
const res = await fetch(`${hostname}/api/user`, options)
const json = await res.json()
if (json.data) { data = json.data }
// do some math with data ...
// connect to MongoDB and do some comparisons, etc.
3
Answers
You want to use the logic that’s in your API route directly in
getServerSideProps
, rather than calling your internal API. That’s becausegetServerSideProps
runs on the server just like the API routes (making a request from the server to the server itself would be pointless). You can read from the filesystem or access a database directly fromgetServerSideProps
. Note that this only applies to calls to internal API routes – it’s perfectly fine to call external APIs fromgetServerSideProps
.From Next.js
getServerSideProps
documentation:(Note that the same applies when using
getStaticProps
/getStaticPaths
methods)Here’s a small refactor example that allows you to have logic from an API route reused in
getServerSideProps
.Let’s assume you have this simple API route.
You can extract the fetching logic to a separate function (can still keep it in
api/user
if you want), which is still usable in the API route.But also allows you to re-use the
getData
function ingetServerSideProps
.Just try to use
useSWR
, example belowPlease notice,
fetch
only supports absolute URLs, it’s why I don’t like to use it.P.S. According to the docs, you can even use
useSWR
withSSR
.As I admit, what you say is correct but problem still exist. Assume you have your backend written and your api’s are secured so fetching out logic from a secured and written backend seems to be annoying and wasting time and energy. Another disadvantage is that by fetching out logic from backend you must rewrite your own code to handle errors and authenticate user’s and validate user request’s that exist in your written backend. I wonder if it’s possible to call api’s within nextjs without fetching out logic from middlewars? The answer is positive here is my solution:
npm i node-mocks-http
important NOTE: don’t forget to use
await next()
instead ofnext()
if you use my code in all of your middlewares or else you get an error.Another solution: next connect has
run
method that do something like mycode but personally I had some problems with it; here is its link:next connet run method to call next api’s in serverSideProps