Internal API fetch with getServerSideProps? (Next.js)
But then I read in the Next.js documentation that you should not use
fetch()
to all an API route ingetServerSideProps()
.
You want to use the logic that's in your API route directly in getServerSideProps
, rather than calling your internal API. That's because getServerSideProps
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 from getServerSideProps
. Note that this only applies to calls to internal API routes - it's perfectly fine to call external APIs from getServerSideProps
.
From Next.js getServerSideProps
documentation:
It can be tempting to reach for an API Route when you want to fetch
data from the server, then call that API route fromgetServerSideProps
. This is an unnecessary and inefficient approach,
as it will cause an extra request to be made due to bothgetServerSideProps
and API Routes running on the server.(...) Instead, directly import the logic used inside your API Route
intogetServerSideProps
. This could mean calling a CMS, database, or
other API directly from insidegetServerSideProps
.
(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.
// pages/api/user
export default async function handler(req, res) {
// Using a fetch here but could be any async operation to an external source
const response = await fetch(/* external API endpoint */)
const jsonData = await response.json()
res.status(200).json(jsonData)
}
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.
// pages/api/user
export async function getData() {
const response = await fetch(/* external API endpoint */)
const jsonData = await response.json()
return jsonData
}
export default async function handler(req, res) {
const jsonData = await getData()
res.status(200).json(jsonData)
}
But also allows you to re-use the getData
function in getServerSideProps
.
// pages/home
import { getData } from './api/user'
//...
export async function getServerSideProps(context) {
const jsonData = await getData()
//...
}
Is fetch inside getStaticProps and getServerSideProps the same as the native browser fetch API?
So my doubt is we only write server-side code and node.js doesn't have a native fetch API, so what fetch API is used inside getStaticProps and getServerSideProps?
In the Node.js environment (getStaticProps
, getServerSideProps
and API routes) Next.js uses node-fetch
to polyfill the fetch
API.
nextjs: how can I do a fetch on a local path?
You can do it like this fetch('http://localhost:3000/api/get_all_prices')
or replace the base URL with a variable fetch(baseUrl + 'api/get_all_prices')
which might cause error: Only absolute paths are supported
.
However, you should only call local API for testing because...
You should not use fetch() to call an API route in getServerSideProps
this is mentioned in the documentation
It is recommended to write your logic directly inside getServerSideProps
.
This applies to getStaticProps
too.
NextJS generate page getServerSideProps to getStaticProps
I saw an article on MongoDB, here is the link, just don't use internal API and then fetch data direct to MongoDB in getStaticProps, here in my code.
BEFORE
export async function getServerSideProps() {
const response = await fetch(`${server}/api/gallery`);
const data = await response.json();
if (!data) {
return {
notFound: true,
};
}
return {
props: { data },
};
}
AFTER
export async function getStaticProps() {
await dbConnect()
//connect to mongodb
const gallery = await art.find()
//i use mongoose model to fetch data
return {
props:{
data:JSON.parse(JSON.stringify(gallery))
}
}
}
How to share data between API route and getServerSideProps?
You could use Node.js global
object to share data between API routes and getServerSideProps
.
For instance, you could set the data in the getServerSideProps
function.
export const getServerSideProps = async () => {
// Set data in `global` object
global._SOME_DATA_ = { data: { hello: 'world' }, ttl: '3600' }
// ...
}
Then retrieve that same data at a later point in the API route.
export default async (req, res) => {
console.log(global._SOME_DATA_) // Logs: `{ data: { hello: 'world' }, ttl: '3600' }`
// ...
}
Related Topics
Open Url in New Tab or Reuse Existing One Whenever Possible
How to Get All the Applied Styles of an Element by Just Giving Its Id
Target='_Blank' to Show in New Window, Not New Tab, Possible
Open a New JavaScript Window(.Open) Along with Its CSS Styling
Decoding Url Parameters with JavaScript
Python Library for Rendering HTML and JavaScript
How to Disable the Save Password Bubble in Chrome Using JavaScript
JavaScript Change Background Color on Click
JavaScript Beforeunload Detect Refresh Versus Close
Html:Draw Table Using Innerhtml
How to Open a File Browser with Default Directory in JavaScript
What Is the Purpose of the HTML "No-Js" Class
How to Remove an Item from an Array in Angularjs Scope
Wait 5 Seconds Before Executing Next Line
How to Change an Element Type Using Jquery