Context
I’ve been building a web app with nextjs and a custom backend in Django Python and I’ve been struggling to find a clean way to make API requests to my backend from Nextjs. What I’m looking for is a way to centralise the logic for the fetch function while adding type safety to the request body and responses.
Current approach
const api = {
get: async function (url: string): Promise<any> {
console.log("get", url);
return new Promise((resolve, reject) => {
fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}${url}`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
cache: "no-store",
})
.then((response) => response.json())
.then((json) => {
console.log("Response:", json);
resolve(json);
})
.catch((error) => {
reject(error);
});
});
},
post: async function (url: string, data: any): Promise<any> {
console.log("post", url, data);
return new Promise((resolve, reject) => {
fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}${url}`, {
method: "POST",
body: JSON.stringify(data),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((json) => {
console.log("Response:", json);
resolve(json);
})
.catch((error) => {
reject(error);
});
});
},
}
In this approach, I am centralising the logic for get and post requests in the sense that now I can just import api and call api.post/get to make a request to my backend. However, I don’t like repeating code for future methods such as patch and delete. The biggest issue I have with this approach is I have lost all type safety since the GET and POST return data of type any and the POST accepts data of type any… no bueno.
Route handlers
I have also looked at Nextjs documentation on route handlers route handlers, but I feel that this runs into the same issues: Either you have to repeat the code for fetch every time you want to make a request to the backend or you centralise that logic but then lose type safety. I also don’t like creating an entire file for the purpose of a GET request.
The discussion
Although I would appreciate an answer to this problem specifically, in the bigger picture how do you guys set up a clean API in Nextjs that reuses code for the fetch API, adds type safety, and is easy to read/clean?