Next.js Discord

Discord Forum

Fetching from the server with Route Handlers from an external API ?

Answered
Ocicat posted this in #help-forum
Open in Discord
Avatar
OcicatOP
Hi all.
This is a conceptual question. In my Next,js 14 app. I have an external API that I want to make requests to. Doing it on the client would expose the secret API key.

One option would be to do it on the server via route handlers. But then I'm told it's highly discouraged to fetch from the server, and that it can slow down or even brick your app.

How do I solve this conundrum?
Thanks for your help!
Answered by Asian black bear
Well then just wrap the input with a form and a server action that takes the input value, stores it in your database and uses your external API for it and you're done
View full answer

75 Replies

Avatar
American Chinchilla
Hmm im not sure where you heard that
Avatar
OcicatOP
@American Chinchilla , what do you mean?

I can fetch from the server with route handlers, no problem?
That is, from an external API?
Avatar
American Chinchilla
Yes, because it runs in the server so it wont affect what the user sees
Unless like its a very big request
But even so most request is done quickly on server side
Avatar
OcicatOP
No, it's a tiny request. WHat about the admonission not to fetch from an etxrenal API from the server? Is it an urban myth, then?
Avatar
American Chinchilla
You want your secret key then to be on the api if its only for that single api
Im not sure where you heard that from
If you could link the article
I can take a look and others in this channel too.
Avatar
OcicatOP
I'm quoitng from memory, and chatGPT confirmed it, stating that , generally, it's not advised as it can slow down your app . I seem to recall it could even brick your app.

Am I remmebring it wrong?
Let me see if I can pull GPT quote here
It's giving me a differnt answer, this tiome around...
@American Chinchilla , so in your opinion, there's no problem with fetching from the server via Route handlers, from an external API? I should go for it?
Avatar
American Chinchilla
Its not my opinion
Its mentioned in the official next.js doc
Avatar
OcicatOP
@American Chinchilla , thanks. Maybe I remembered wrong, and GPT screwed up as well. 😄 . Happy ending!
Avatar
Alfonsus Ardani
can confirm that is bs, not sure where you get that from
yes it can slow down server but with proper caching and streaming technique it shouldnt be an issue
Avatar
Asian black bear
fyi you are probably mistaking this with fetching your own server from itself which doesn't make any sense.
Avatar
OcicatOP
@Asian black bear , I have tried it toay and it does work.

I'm making calls to an external API. Instead of making them from the client , which would expose the API key, I have created a miiddle-man Route handler. So the client hits the route handler, which runs on the server, amd the route handler hits the external API, gets the response and formats it and returns it to the cleint.

Does this look sound to you?
Avatar
Asian black bear
If you have a server component you can just fetch directly in it without the need to have a route handler unless you are forced to use client-side fetching for some reason
Avatar
OcicatOP
@Asian black bear , yes, I have all sorts of hooks that require client-components
Avatar
American Crow
Thats not what he meant. The RSC way is to fetch (get data) in a server component and pass the data down to the client. You can have hooks there and all kinds of interactivity.

However you are "forced" to fetch on the client if you need to implement something like polling (fetching in short intervals) aka "my data needs to be super fresh all the time", infinite scrolling, ..

So if you are not forced or have no use case for client side fetching, you always fetch in a server component (directly, no route handlers, no middleman) and pass the data down to the client comp.

If you are "forced" to use a client component you need the route handler man in the middle to not expose secrets
--
Note Referring to fetching here only in the sense of getting data. Usually fetching can include both: get and manipulate (post/delete/update) data. The latter would be a different use case with different tools (mostly server actions, some cases again route handlers) to complete the task
Avatar
OcicatOP
No, in this case , data will be fetched very infrequently.

Let me see if I'm getting this right @American Crow . 1. I have UI that requires hooks, therefore requires client components. So client components would pass the request details to the server component. 2. Server component would fetch data directly from extrenal API 3. Server component would pass fetched data back to cleint component?

Is this it?

And the best way to pass data to and from client and server components is the Conetxt API?

Thanks for your help. It's appreciated!
Avatar
American Crow
Make an example for why the client component determines the "request details" which need to be passed to the server component for getting data
And the best way to pass data to and from client and server components is the Conetxt API? Its never this the server has no access to any state.
The general data flow is form the server to the client. There are some ways around it, thats why i am asking for an example
Avatar
OcicatOP
Let's say my input fields have lots of interactivity that require hooks and the UX is therefore very differnt from what you'd get with server componets/ server actions
Avatar
Asian black bear
It's not
Because form submissions can be done with actions
Avatar
American Crow
Yea that's why i said separate between getting data and manipulating data
Avatar
Asian black bear
Regarding your very initial question: yes, using a route handler as a proxy to hide secrets is correct.
But with server components and server actions you can very likely move everything into more idiomatic code that doesn't need route handlers.
Route handlers are only meant for 3rd parties interacting with your public API and things that definitely have to be run client-side from your own app which is fairly rare.
Avatar
OcicatOP
What I'm not getting is that hooks don't work on server components. If my UX requires hooks, then I have to set up an architecture that uses both client and server compoennts and somehow makes them talk to each other. Am I seeing this wrong?
Avatar
Asian black bear
Server and client components can be interleaved and server actions or data you fetch server-side can be passed on to client components
Avatar
OcicatOP
If I have an input field that uses state to animate something on focus, let's say, I wouldn't be able to convert that to server compoenents in a 1-to-1 fashion, right?
So what's the best, correct way to pass data from server componenst to client components? Props? Conetxt?
Avatar
Asian black bear
It is pointless to vaguely discuss anything without any concrete example
A text input can be either server or client component, depending on the specific needs
Data fetching can always be done server-side and rendering as well
If client components need the data they can be passed as props most of the time
And form submissions can be done using server actions
Avatar
OcicatOP
But you wouldn't be able to have the input react to a change of focus with some sort of aniamtion taht requires useState in a server component with an input, right?
Avatar
Asian black bear
If you don't use a pure CSS solution it specifically has to be a client component but that doesn't change the bigger picture of the other points
Avatar
OcicatOP
So if the animated input is a client component , the cc must then pass data to the server componnent, sc. Sc fetches data. Then Sc has to pass data back to either a new SC or teh original CC. This is the architecture. It has to be two-way data communication , am I right?
Avatar
Asian black bear
Way too complex. The form wrapping the fields can have a server action as a handler that deals with the form submission.
Avatar
American Crow
You have to specify what the server component does with the user input. Lets say the user inputs "abc" in the input. What do you want to do with that ?
Avatar
Asian black bear
Why don't you share your exact use-case instead of attempting to be so generic in your description.
Avatar
OcicatOP
Ok, In this case user will input an address and a call will be made to get geocoordinates. I have created my own component library , so I was looking to reuse those client components in this form as in all forms. These cleint components animate on focus, hover, etc
Avatar
Asian black bear
And you want the page to show additional content after the use has entered an address?
Avatar
OcicatOP
Not necessarily. Those geocoordinates will be saved along with the address to the database. That's the key thing. Showing the result of the geolocation is not terribly important.
Avatar
Asian black bear
Well then just wrap the input with a form and a server action that takes the input value, stores it in your database and uses your external API for it and you're done
Answer
Avatar
American Crow
damn thats the easy case @Asian black bear i let you answer it but i'd love to know how you'd have done the other case you descibred (addtional content after user entered adress)
Avatar
Asian black bear
Search parameters either when typing in realtime or on form submission: https://nextjs-faq.com/sharing-client-side-state-with-server-components
Avatar
OcicatOP
So in essence, the form remains a server components that embeds inputs that are client components, right? And the form, sc, can then perform a server action?
Avatar
Asian black bear
Yes
Avatar
OcicatOP
Ah ah!
Lightbulb moment!
Avatar
American Crow
love to hear that. I just had the debate in my head i really want to avoid server actions to get data (aka blocking, sequential in nature). OP ignore this message this most likely just confuses you. I('d have also used serachparams)
Avatar
Asian black bear
Just consider pages the result of any kind of GET request and use search params to pass data to the server then it becomes trivial dealing with it and it makes it trivial with links that are even shareable
Avatar
OcicatOP
Is there a name to this pattern, so I can research it further?
Avatar
American Crow
Don't think there is a name for it but it's described here:
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#convention
It seperates between using server actions in server components and client components
Avatar
OcicatOP
Thanks @Asian black bear and @American Crow for your guidance. It's very much appreciated!
Avatar
American Crow
Just a little extra: You can even make the submit button itself a client component to get pending states while the form is submitting
Avatar
OcicatOP
Exciting stuff. Lots to learn and implement. Going to be a long weekend! 😄
Avatar
American Crow
Be so kind and mark one of @Asian black bear answers as solution to this thread so others can benefit. (right click a message -> app -> mark as solution)
Avatar
Sawfly parasitic wasp
Hello ! I had more or less the same question that I posted on stackoverflow :

https://stackoverflow.com/questions/78547999/need-advice-on-next-js-14-and-external-api-fetch-logic

So if I understand, I should basically use the router handlers for external api call in my server components ? Seems a bit overkill when knowing that the external api is done already. Coming from basic react apps, I feel like writing some extra code that is usually handled by a simple fetch in a client component in normal react
Avatar
joulev
In my current project, I fetch users in my Users server component
<code>
I'm using server actions to fetch my users:
<code>
You are not using server actions. Since the function is run in a server component, it runs on the server already, so it just behaves as an ordinary javascript function. It will only behave as a server action when you run it from the client.

First of all, I'm not even sure that I should be using a GET to fetch my users with a server-action even though it seems to be working. [...]
You are using GET, since you are not using a server action. Your code is good.

In a second place, I can't useSession from next-auth to get the token in my fetchWrapper function to add it for each request. So for not it's hardcoded token that I need to replace manually every time.
Yes because it's run in the server. The server-side function to get the session is getServerSession

I also read about the route handlers, but since i'm using an external api I don't really see the point of using these.
No point
Avatar
Sawfly parasitic wasp
Thanks @joulev

You are using GET, since you are not using a server action. Your code is good.

Does it mean that if I use a server action from a client component, it will only use POST method? I'm confused about server actions usage. Can I perform other methods like GET, PUT, etc, and it's still a server-action if executed from a client component ?


No point
Is the fetchWrapper function to add authorization token a good practice in my case?
Avatar
joulev
Does it mean that if I use a server action from a client component, it will only use POST method? I'm confused about server actions usage. Can I perform other methods like GET, PUT, etc, and it's still a server-action if executed from a client component ?
the client will trigger the server action by a POST request to the url of the page. inside the action you can use any request methods you wish.

Is the fetchWrapper function to add authorization token a good practice in my case?
a wrapper for things like this is very common. that said don't hardcode your api key, make it an environment variable instead
the part about the POST method of server action is just an implementation detail of how server actions work behind the scenes. it doesn't affect your application and you need not worry about it