Correct and Secure way to handle forms in Nextjs
Unanswered
Serengeti posted this in #help-forum
SerengetiOP
I am working on my own project - turborepo with apps/web ( Nextjs ) and apps/api ( Nodejs ). apps/api solely handles the whole business logic.
I am confused about how to handle forms for my web app. I have read a lot of Reddit articles about Server Actions not being secure. On the other hand, API Routes don't seem to be the right way of handling form requests ( I am also confused about why I ever need them ).
I am also considering using 3rd party library like Tanstack Form or React-Hooks-Form. Can you please share your experience?
In Summary
- Why would I use api routes?
- Are Server Actions the right way to handle form requests?
- Does Tanstack Query solve the same problem as api routes?
- Does Tanstack Form solve the same problem as Server Actions?
I am confused about how to handle forms for my web app. I have read a lot of Reddit articles about Server Actions not being secure. On the other hand, API Routes don't seem to be the right way of handling form requests ( I am also confused about why I ever need them ).
I am also considering using 3rd party library like Tanstack Form or React-Hooks-Form. Can you please share your experience?
In Summary
- Why would I use api routes?
- Are Server Actions the right way to handle form requests?
- Does Tanstack Query solve the same problem as api routes?
- Does Tanstack Form solve the same problem as Server Actions?
13 Replies
@Serengeti I am working on my own project - turborepo with apps/web ( Nextjs ) and apps/api ( Nodejs ). apps/api solely handles the whole business logic.
I am confused about how to handle forms for my web app. I have read a lot of Reddit articles about Server Actions not being secure. On the other hand, API Routes don't seem to be the right way of handling form requests ( I am also confused about why I ever need them ).
I am also considering using 3rd party library like Tanstack Form or React-Hooks-Form. Can you please share your experience?
In Summary
- Why would I use api routes?
- Are Server Actions the right way to handle form requests?
- Does Tanstack Query solve the same problem as api routes?
- Does Tanstack Form solve the same problem as Server Actions?
a lot of Reddit articles about Server Actionsserver actions are as secure as you make it to be.
its the idiomatic way to mutate data in the front end.
care to elaborate how you find server actions not being secure?
Why would I use api routes?You would need api routes if
1) you need more advanced mutation than server actions,
2) external client (like mobile apps) accessing the API
3) client-side data fetching
Are Server Actions the right way to handle form requests?it is the simplest, most idiomatic way to handle form request, but it isn't the only way nor is it the "right" way. it depends on your UX use case
Does Tanstack Query solve the same problem as api routes?nope. Tanstack Query is an async state management not a data fetching library. It manages when and which data needs to be fetched, but doesn't change how data is fetched. You can either use server aciton or fetch() or ky() or axiom as data fetching solution
Does Tanstack Form solve the same problem as Server Actions?nope. Tanstack Form provides type-safe form but doesn't define what happened when forms are submitted (after validation and all stuff needed to be done in the client-side)
server actions are just opinionated approach to abstract API routes that couples with UI updates while improving type-safety
SerengetiOP
I need to read a lot about them first. Thanks for your detailed answer. I will get back here again, once I have a clue on what is what.
take your time!
SerengetiOP
@alfonsüs ardani Seems like I can now understand the nature of Server Actions. Here arises another conceptual decision.
Imagine a situation - Nextjs handles the web app rendering on the server. On the client, I use Tanstack Query to handle the client side requests.
- Do I still need Server Actions to act as an intermediary between api and client?
- Can't I directly call api on the client? ( I know I can, but what is the tradeoff )
- Using Tanstack Query with Server Actions to call the api adds additional data roundtrip
Option 1 - Tanstack Query handles client side request and delegates to Server Action -> Server Action handles the request and delegates to api ( Dedicated Nodejs API Server )
Option 2 - Tanstack Query hanldes client side request and directly calls Dedicated API Server ( No Intermediate Nextjs Server Action )
Imagine a situation - Nextjs handles the web app rendering on the server. On the client, I use Tanstack Query to handle the client side requests.
- Do I still need Server Actions to act as an intermediary between api and client?
- Can't I directly call api on the client? ( I know I can, but what is the tradeoff )
- Using Tanstack Query with Server Actions to call the api adds additional data roundtrip
Option 1 - Tanstack Query handles client side request and delegates to Server Action -> Server Action handles the request and delegates to api ( Dedicated Nodejs API Server )
Option 2 - Tanstack Query hanldes client side request and directly calls Dedicated API Server ( No Intermediate Nextjs Server Action )
@Serengeti <@194128415954173952> Seems like I can now understand the nature of Server Actions. Here arises another conceptual decision.
Imagine a situation - Nextjs handles the web app rendering on the server. On the client, I use Tanstack Query to handle the client side requests.
- Do I still need Server Actions to act as an intermediary between api and client?
- Can't I directly call api on the client? ( I know I can, but what is the tradeoff )
- Using Tanstack Query with Server Actions to call the api adds additional data roundtrip
Option 1 - Tanstack Query handles client side request and delegates to Server Action -> Server Action handles the request and delegates to api ( Dedicated Nodejs API Server )
Option 2 - Tanstack Query hanldes client side request and directly calls Dedicated API Server ( No Intermediate Nextjs Server Action )
I havent personally used Tanstack Query myself but Id imagine you'd rather use API handler with Tanstack Query since its more fitting for its intended use case for each library.
Server Actions are designed for mutations are not data fetching. Tanstack Query requires a function for its data fetching purposes. fetch() calls are more fittin here.
That being said:
You need to manually cast the return type and the input types.
You need to manually serialize inputs and outputs
You need to handle race conditions
But you gain mroe control with non server-action approach.
I think its getting more complicated than it needs to be.
Tanstack Query offers ways that works with Next.js paradigm. Which is to fetch data in the server and pass it to
Server Actions are designed for mutations are not data fetching. Tanstack Query requires a function for its data fetching purposes. fetch() calls are more fittin here.
That being said:
Do I still need Server Actions to act as an intermediary between api and client?You might still need Server Actions for Form mutations or onClick handlers and benefit from it.
Can't I directly call api on the client? ( I know I can, but what is the tradeoff )Yes you can, the tradeoff is type-safety and serialization.
You need to manually cast the return type and the input types.
You need to manually serialize inputs and outputs
You need to handle race conditions
But you gain mroe control with non server-action approach.
I think its getting more complicated than it needs to be.
Tanstack Query offers ways that works with Next.js paradigm. Which is to fetch data in the server and pass it to
QueryClientProviderthen whenever you do useQuery, it wont do double roundtrip because it already detects that it has received data from the server so theres no need to re-fetch unless the data is stale
Option 2 works too if you dont have Nextjs-as-a-backend
SerengetiOP
Thanks a lot for your detailed explanation and for your time. Now, I have more understanding of which approach would fit my requirements
SerengetiOP
I still have more questions as I am exploring more articles and opinions.
Let's assume I am going with Option 2
- How do I revalidate a server function?
- What about Data Cache?
- How much increased latency should I expect?
The point here is you lose the benefits of Nextjs or maybe I still can have them ( Dont know how )
Let's assume I am going with Option 2
- How do I revalidate a server function?
- What about Data Cache?
- How much increased latency should I expect?
The point here is you lose the benefits of Nextjs or maybe I still can have them ( Dont know how )
@Serengeti I still have more questions as I am exploring more articles and opinions.
Let's assume I am going with Option 2
- How do I revalidate a server function?
- What about Data Cache?
- How much increased latency should I expect?
The point here is you lose the benefits of Nextjs or maybe I still can have them ( Dont know how )
Then your backend handles all the caching and the latency...
There is no nextjs server function therefore no data cache therefore no need to revalidate?
All is done in the client
There is no nextjs server function therefore no data cache therefore no need to revalidate?
All is done in the client
Its not losing benefits if you plan to reimplement them in your own backend...
Server actions are still api routes nehind the curtain so not using them you just decouple from nextjs's ecosystem
Server actions are still api routes nehind the curtain so not using them you just decouple from nextjs's ecosystem
Im sure there is an example setup to correctly integrate tanstack query with nextjs but just keep in mind that if u want best of both worlds then you have to double the complexity