I don't know how anything works anymore in these frameworks and I HATE it. I hate just using it because the documentation says so. Not knowing what goes on behind the scene annoys me. I understand Server Components and Server Actions now thanks to you clearing things up for us, I hope they don't bring crazy changes in like a week or something, we need stability.
Yes! You spoke to my heart! They just keep on adding more magic thinking that we'll just keep gobbling it all up. Everything that's trending now will be deprecated in a few months and there will be a new NextJS version to "fix" everything. Also I question the ethics of Vercel where I see them making react more of a mess and server oriented increasingly to their benefit and they've completely overtaken the react project as of now
Exactly this. I used to love next.js. I do work with angular at work and with nextjs on my personal project. And at this point I can safely say that I really starting to love angular and hate nextjs. Like angular seems way simpler to me at this point, less of that magic, routing is straight forward, etc. I don’t know, I’m just venting at this point.
@@qwerty-or1yg solidstart looks promising but it's still in beta. if you like rust there's leptos which is essentially a clone of solid/solidstart in wasm. i think leptos is actually more intuitive and less verbose in a lot of ways, especially for server functions, because it's just a macro. server/client code is colocated so you don't have to deal with all of these client/server files everywhere. unfortunately javascript as a language is limited which is why 'use server' etc is even a thing.
This is just pure madness at this point. This all feels very similar to all the useEffect issues. Instead of cleaning up those APIs, they just build on top of them and try to further abstract their own mess. Also feel like Theo is just lobbying for Vercel at this point without questioning any of this. I think this is a good time to switch back to something like Rails/Laravel or maybe SolidStart/SvelteKit if you want to stay in JS world.
No sir, I believe you meant the other way around as in "Vercel lobbied Theo". And yes, this type of shit is life-ruining to not a small number of developers who entered this field in good faith, as they will never find solace in the "skill" or "craft" in which they sacrificed all aspects of social life and connections(things that matter and have real life consequences) to attain. Welcome to React 2023, where the theme for this year and perhaps many more to come is: "Let's build castles on sand."
Wow, this looks super production ready and stable and battle tested. And DX is super. Dopamine hit for my brain. What can go wrong? Waterfall = bad, magical stuff = good. Solves so many issues that we did not have. Immaculate doesn't even begin to describe this.
If nothing else this should be a clear signal for an average JS developer to jump ship and learn something better because this is bending what Javascript is supposed to be to a point that it can be just a new language. And remember, *whatever that is trending right now will be a deprecated practice a few months from now* especially with how fast this thing previously called react is mutating
@@ivan.jeremic hmmm, i don't think it's completely unreasonable to dislike that they're fixing an issue their own approach created, especially when that approach required a significant shift *away* from web/html fundadmentals in the first place.
@@ivan.jeremic buddy in simple words I am saying is next js is too much magic for me personally. I don't want to keep learning everything from scratch every third month when they decide to add some more revolutionary ideas that is supposed to improve "DX". Web development is supposed to be simple you create a frontend and a backend and just make them talk using REST, GraphQL or RPC and that's it. Anything more complicated than that is mental illness and nothing but premature optimizations
@@dough-pizza So basically you dont care about UX? RSC doesnt solve DX problem, and all those updates not about DX. Prev, you could generate some code on BackEnd then you would have your React code send to FrontEnd, where it is hudrated from Json type to VDom with html and you would have so much more code send and used for simple stuff. With RSC you also send from BackEnd your code, but now you dont send your "React code" useState, useEffect and then hydrate it on client side. You send already hydrated Json, that just embedded to VDom
You should definitely talk about error handling in server action, especially server action on RSC. It seems we have to use the fallback error component for it, and it's hard to make a good UX like client components do.
Maybe not totally related, but you can do that with Zod and next-safe-action. I am currently using it in production. You get a {data, validationError, serverError} object from the next-safe-action and then you can do anything you need with that. In my case I am running zod on client and server side. If there is a validation error on client, it doesn't post the action ofc. If there is a validation error from the server side (shouldn't happen, but for some reason if it does) or a server error (e.g. getSomething(ID) and ID is not found) I show a toast to the user
They just can't show you error handling, cause if they do they'd break progressive enhancement and "lego pattern with react". So they show only marketing videos to promote vercel
@@lpmacau I see this, great lib. I just take a look at the example, it is a client component example, server action for client component is much more easier because action just like a normal api call. So as I saied, for RSC, the problem become much more complicated
Server actions in a different file is what I did with the experimental flag and what I continued doing after upgrading my project. I really don't like mixing my client & server code. Something really cool with that is that you can still share definitions between client & server while at the same time maintening a good old separation of concern.
0:29 - That was MY source code that fundamentally misunderstands server actions!! I've never been so happy to nerd snipe someone and not only get personalized help but a YT video out of it! Incredible resource Theo, thank you so much for putting together this repo as it has already helped me grok server actions much better!
Just a few notes base on my recent dive into server actions. All data going into your server action doesn't have to be included in the form itself. You can pass in additional args through bind (e.g. . Also, and this is a bit of an ugly hack, you can force React to clear your form fields on revalidation by changing their keys. I do it by setting their key to performance.now() (e.g. ). No need to create a client component just for that. Additionally, I suggest you use redirect("/path") instead of revalidatePath("/path") at the end of your server actions because, when running with JS disabled, refreshing the page after submitting a form will cause it to submit again (old school webdev problems frfr).
As I have a separate backend I won't be moving off tRPC anytime soon but even if I didn't, I have to say I still much prefer tRPC over the way they showed server actions directly in components, I like the client server separation. Throw in middleware, context and the other useful features that tRPC provides and I think it clearly offers a better DX than server actions do. Big fan of server components but server actions, not so much
I have been using react for two years I used redux, redux-toolkit, react query etc But I didn’t used trpc because you could have to consume a backend different than NodeJs with typescript and it’s enough to use react query Also I found “use-server” very confusing and not completely necessary, because we have easier to understand alternatives to do this. The main advantage of using use-server is saving some lines of code and declaring types. But do you think it is worth it to confuse an entire community for this purpose? When you code not only T3 will read your code and will understand it, but other people will have to do it. And trust me, is better to put things clear to other people.
@@philheathslegalteam Im mainly front end developer, my coworkers take care about implementing swagger and openAPI specification But I would do if needed :) Although I wouldn’t use python or php for my side project backend, Trpc and T3 stack is completely perfect when you aren’t attached to a company
@@bules12 good stuff then its not problematic at all. OpenAPI typescript can make react query and SWR act the same way as tRPC with e2e typesafety. Or if you’re just using raw react query you at least have the types clearly defined by the API
Everyone was so gloom and doom about tRPC dying once RSC drops :) and turns out that tRPC is the perfect layer to call from your server actions even if you don't use client components from tRPC
Well, server actions looks good only if you plan to use your api on your nextjs project and nowhere else. The day another team will request you an access to an endpoint of your company from their tools, you will have to write a new backend for them lol
Right off the bat it feels so unintuitive to know that you had to structure things inside of a form. so many things implicit or abstracted in a way that feels easy to do things wrong
After installing create-t3-app, and watching your guide about T3 stack, this video is right what I needed! You have shown how to use createCaller, server actions standalone, and with tRPC, which is very convenient! Also, please explain, which pattern works best for you, which is you default approach between these 4 now?
I’ve been using the pattern for calling server actions from client components with startTransition and for me it’s the best one. Yes, sometimes I have to create the client components just for this but a lot of times my forms will include logic that calls for client components like client side validation, immediate feedback, etc.
Do the performance benefits outweigh the added complexity? Maybe. I’m gonna fiddle with this in a side project to see if it’s worth using, but for production apps I still feel like I’m leaning towards client side for most complex use cases. I’ll probably throw in server components and actions for small simple forms or view only sections of the app
API security really isn't an irrelevant detail. Are those hidden fields in the closure replayable? Do they have perfect forward secrecy? Are there session-stealing style vulnerabilities here? Making the mechanism explicit makes it clear what trade-offs are being made. If you care about being explicit with types, you definitely want to be explicit about the security properties of your system.
I just use telefunc and no issues at all, this also comes at a benfits of getting rid of nextjs, trpc, tanstack query, etc that slow down everthing. Basically I use one that remove 3-4 other dependencies.
Super helpful video - thanks Theo! Sometimes, because of all the ways our minds have changed with TRPC, using createCaller still feels a little wrong, but this video helps justify it and the fact that I need to spend time doing the mental model shift.
I almost stormed out of the room with frustration watching your video but glad I stuck it out to the end. That last pattern is definitely the way forward. The other patterns are just DX when writing code around forms but ultimately terrible for reading/maintaining code
I am currently using the trpc client approach and I am having problems with refreshing page content. Could you do something on Next caching? I feel like there is no good way to invalidate a specific page other than the one you are currently on with the trpc client approach. For example imagine a page /editContent where an admin can edit a database entry which is displayed at /content. How would I inform the client, that its cache for /content is invalid? I would need to invalidate the cache for every client currently storing the old content of /content.
I am playing around with app router and all of its things for a while now, and it seems pretty magical. In a positive and a negative way. If you understand how everything is intended to be used, you can really fly doing things. But things are getting so implicit and are losing the self-explaining part that e.g. page router has, that it's hard to keep up to date, and master the thing. I'm not even starting on how it must be like if you are working in a bigger team with engineers that are not as passionate as most of us are.
You can actually use async at the top level for the API createCaller logic, just await the creation of the context prior to passing it into the function and it seems to work just fine, since NextJS supports top level await.
Do you mean adding something like: const user = await currentUser(); // e.g. Clerk's currentUser function export const api = appRouter.createCaller({ db: db, headers: headers(), user: user, }); ? Are you 100% certain that all of this code is run again and again per request, and not persisted across requests somehow (leading to different users using each other's sessions)? I have bad experiences with setting unscoped variables like this in Next, since it used to persist across requests in the pages router.
I totally appreciate the work you do to make these concepts clearer for all, but The mess called js frameworks we're pushing is just absurd. This is discouraging beginners to get into web dev. Because of the millions of things we are pushing to be in this space, the moment you go back to edit a nextjs app you build last year November, you start seeing crazy errors and package updates with api changes and no other dev can make changes.
Omg that side effect confused the crap out of me when suddenly I didn’t need formData in that separate file and everywhere the docs keep talking about forms…. I thought I had done something wrong lol
Is that just next js or is that react implementation? Because it would be very nice to have this "action" endpoint that has many action types automatically created easily outside of next. By biggest fear is react just becoming next.
Really helpful video and I really like the last one! I'm new to app router and I'm currently doing `Object.fromEntries(formData.entries())` for my server actions then parsing it with a zod schema of my expected shape. Any drawbacks to doing this?
This shit was the last straw before I quit Javascript. I converted from fullstack JS engineer to non-JS backend engineer and I'm never touching JS again unless I'm the one making the decisions. I'm getting too old to deal with the hyperactive JS monkeys "innovating" just because.
The argument is that it's more efficient to split rendering between the client and server, instead of rendering everything on both. I'd argue that for the vast majority of projects, it isn't worth the effort.
@@heaps. I generally take the SSR-> hydrate into SPA approach since it sounds the lost sensible to me tbh. It keeos server load somewhat low (nice for me since I gotta pay that), devices are easily performant enaugh to hydrate quickly and make everything very fast and snappy... so the ssr-> hydrate spa sounds the best of all worlds with virtually no downsides to me... still (ofc not everything needs it and probably easier to implement solution would be suggested)
I'm new to nextjs so forgive me if this is a stupid question - but why does revalidatePath show the new content? docs seem to say it clears the cache, so it's not actually sending the new data to the client until they refresh, right?
Also, is it a reasonable mental model to think of it as the form sending a reference to the function to be called, that would have traditionally been called by a controller in express? So instead of hitting '/somepath' and having `Controller.doSomething()` run, the form just has the action `doSomething()`? Anyway, love the videos 👍 *edit: oh, it's a closure not a reference?
@@nickwoodward819 And regarding your other question: When you write a server action, an endpoint is created on the server once you start it. When you call the action in your code, at runtime that endpoint is called. The form, when a user interacts with it on the client, has no access to the action you wrote because it lives on the server. It instead calls the endpoint associated with your action. You mentioned closures in your edit: You are allowed to use closures in your server actions when writing them inside a component. Since the outside is React code, and it might live on the client, they needed a way to save that closure data. So they added a few encrypted, hidden inputs that are sent alongside the form data to the server action endpoint. This is the reason that if you define server actions in a component, you can only do that in forms (via the "action" prop) or buttons (via the "formAction" prop) inside a form. This is my understanding up to now, at least. Hope that helps!
First reply got removed, presumably due to me posting links. Let's try again: It's definitely not a stupid question. You're right, the docs don't explicitly state this in the revalidatePath or revalidateTags docs, which is where you expect them to state that. But other parts of the docs do in fact state it: "Further, the browser does not need to refresh on form submission. In a single network roundtrip, Next.js can return both the updated UI and the refreshed data." See the nextjs documentation at /docs/app/building-your-application/data-fetching/forms-and-mutations#revalidating-cached-data And: "There are two ways you can invalidate the Full Route Cache: Revalidating Data: Revalidating the Data Cache, will in turn invalidate the Router Cache by re-rendering components on the server and caching the new render output." See the nextjs documentation at /docs/app/building-your-application/caching#invalidation
I would call the server action directive "use another footgun". React is certainly pushing the community forward, but it relies on weak abstraction foundations like VDOM and useEffect and instead of working on those they keep on adding more stuff that is fragile and hard to make good. Looks like it is time to switch to Solid.js, it can also have server actions in future, after learning on react mistakes
So trpc will just become a simple api for using zod on inputs and outputs. Nobody with react will ever use trpc as a client anymore, its just easier to call the server trpc method itself and a export this pretty async function using server actions.
I strongly dislike everything I've seen about server actions. They don't solve a problem that I have. I'd love to see an example where going all-in on server actions makes sense, especially for teams with non-trivial codebases.
Annoying that the context doesnt work with the callers, how do we protect mutations with trpc in the hybrid pattern then? If this is not possible, I'd call it more an anti-pattern.
Ehh.. server actions = Server-Side useEffect. It's not intuitive. Still hard to wrap your head around. This video demonstrates more Theo's masterful understanding of React and his ability to reason about it than it does to demonstrate easy server action implementation. I appreciate the video because it truly helps. But I'm gonna call Server actions an L for now.
What's confusing about them, are people just dumb? It's just a code on the server you call, like you would write an endpoint and make a post request, but with this you don't need all the boilerplate, and can just use server actions
Enjoyed the video, as usual. Not suuuuper into the aggressive "look at all this value I'm giving you, subscribe or you suck" bit. I'm subscribed, just find it very off-putting
😡 all this is just frustrating. I won’t follow this. My structure is one rest api server (json) handles both web and mobile, web most logic is just view, fetch data from api server in json, if I need ssr I just pull data from the frontend server to api server for initial render, anyone can work on the api server without talking to frontend ever, frontend also never touches the db, everything pass via api server. Easy, simple, no bs
I am about to start working in a similar project with one restaurant api server. I’m probably going to use RSC to do the requests on the server for more performance in the initial rendering. But probably I’d skip server actions as they don’t make much sense in this scenario
I don't see the difference in the 4th action, you are basically using the "use-server" function in a different file. I've been using this for months as well. I don't want my server functions in the same file as the component
Too much magic. Pls link me anything that makes sense of this. Is it making http calls under the hood? Webhooks ? Sockets?? So server actions is generating hidden api endpoints??
Maybe I wasn't paying too much attention, but before watching this video I did not know what server actions are, and I still do not understand anything about them. Your simplest vanilla example still somehow imports from `db`, `trpc`, `next/cache`, and `drizzle` and I don't know what any of these are! Don't know about `db` because it's part of the repo you're showing so I did not see it before, the others - never heard of them. How could that be a simple example? And then it becomes worse. React-query, Data Access Layer, `caller` pattern, "use server", "use-server" but it's in a file, not in a function...
Yeah RSC are trash, I am glad I am now practically 100% backend and I do not have to worry about keeping up-to-date with this shit React is pulling out.
God, JavaScript is such a failure. Watching video made my soul weep. What ever happened to KISS? I'll be sticking to using Vue, Svelte, and React with Go or Python in the back end
I dont get why would anyone need trpc anymore? Even zod on backend? Server actions once exported from a file marked "use server" are fully typesafe and usable on both client and server components, its truly write once and use everywhere, couldn't be more simple. I integrated them with tanstack react query on client components and used it's methods for optimistic updates/revalidating data, passing the action as the fetch function. Am I missing something?
I don't know how anything works anymore in these frameworks and I HATE it. I hate just using it because the documentation says so. Not knowing what goes on behind the scene annoys me.
I understand Server Components and Server Actions now thanks to you clearing things up for us, I hope they don't bring crazy changes in like a week or something, we need stability.
Yes! You spoke to my heart! They just keep on adding more magic thinking that we'll just keep gobbling it all up. Everything that's trending now will be deprecated in a few months and there will be a new NextJS version to "fix" everything.
Also I question the ethics of Vercel where I see them making react more of a mess and server oriented increasingly to their benefit and they've completely overtaken the react project as of now
move to something more stable
Exactly this. I used to love next.js. I do work with angular at work and with nextjs on my personal project. And at this point I can safely say that I really starting to love angular and hate nextjs. Like angular seems way simpler to me at this point, less of that magic, routing is straight forward, etc. I don’t know, I’m just venting at this point.
@@qwerty-or1yg solidstart looks promising but it's still in beta. if you like rust there's leptos which is essentially a clone of solid/solidstart in wasm. i think leptos is actually more intuitive and less verbose in a lot of ways, especially for server functions, because it's just a macro. server/client code is colocated so you don't have to deal with all of these client/server files everywhere. unfortunately javascript as a language is limited which is why 'use server' etc is even a thing.
Couldn’t agree more.
At this point I'll use laravel and inertiajs for my sanity
Laravel ecosystem is so good.
This is just pure madness at this point. This all feels very similar to all the useEffect issues. Instead of cleaning up those APIs, they just build on top of them and try to further abstract their own mess.
Also feel like Theo is just lobbying for Vercel at this point without questioning any of this. I think this is a good time to switch back to something like Rails/Laravel or maybe SolidStart/SvelteKit if you want to stay in JS world.
No sir, I believe you meant the other way around as in "Vercel lobbied Theo". And yes, this type of shit is life-ruining to not a small number of developers who entered this field in good faith, as they will never find solace in the "skill" or "craft" in which they sacrificed all aspects of social life and connections(things that matter and have real life consequences) to attain. Welcome to React 2023, where the theme for this year and perhaps many more to come is: "Let's build castles on sand."
Wow, this looks super production ready and stable and battle tested. And DX is super. Dopamine hit for my brain. What can go wrong? Waterfall = bad, magical stuff = good. Solves so many issues that we did not have. Immaculate doesn't even begin to describe this.
Many sarcasm, strong wow
Some will think you're being serious LOL
@@Dnserror88 I know, sarcasm is a good separation tactic.
If nothing else this should be a clear signal for an average JS developer to jump ship and learn something better because this is bending what Javascript is supposed to be to a point that it can be just a new language.
And remember, *whatever that is trending right now will be a deprecated practice a few months from now* especially with how fast this thing previously called react is mutating
@@ivan.jeremic hmmm, i don't think it's completely unreasonable to dislike that they're fixing an issue their own approach created, especially when that approach required a significant shift *away* from web/html fundadmentals in the first place.
@@ivan.jeremic buddy in simple words I am saying is next js is too much magic for me personally.
I don't want to keep learning everything from scratch every third month when they decide to add some more revolutionary ideas that is supposed to improve "DX".
Web development is supposed to be simple you create a frontend and a backend and just make them talk using REST, GraphQL or RPC and that's it. Anything more complicated than that is mental illness and nothing but premature optimizations
@@dough-pizza So basically you dont care about UX?
RSC doesnt solve DX problem, and all those updates not about DX.
Prev, you could generate some code on BackEnd then you would have your React code send to FrontEnd, where it is hudrated from Json type to VDom with html and you would have so much more code send and used for simple stuff.
With RSC you also send from BackEnd your code, but now you dont send your "React code" useState, useEffect and then hydrate it on client side.
You send already hydrated Json, that just embedded to VDom
Feels like a politician telling ya how good react is where react is top lobby lol
What if we just dont
I think this is the best approach
I think I like that
That's always an option
wow, talk about over-engineered. watching this validates my decision to switch from next to remix.
You should definitely talk about error handling in server action, especially server action on RSC. It seems we have to use the fallback error component for it, and it's hard to make a good UX like client components do.
Maybe not totally related, but you can do that with Zod and next-safe-action. I am currently using it in production.
You get a {data, validationError, serverError} object from the next-safe-action and then you can do anything you need with that.
In my case I am running zod on client and server side. If there is a validation error on client, it doesn't post the action ofc. If there is a validation error from the server side (shouldn't happen, but for some reason if it does) or a server error (e.g. getSomething(ID) and ID is not found) I show a toast to the user
@@lpmacau Wow, super cool that my lib is already used in production!
@@TheEdoRan and works like a charm 😉
They just can't show you error handling, cause if they do they'd break progressive enhancement and "lego pattern with react". So they show only marketing videos to promote vercel
@@lpmacau I see this, great lib. I just take a look at the example, it is a client component example, server action for client component is much more easier because action just like a normal api call. So as I saied, for RSC, the problem become much more complicated
Server actions in a different file is what I did with the experimental flag and what I continued doing after upgrading my project. I really don't like mixing my client & server code.
Something really cool with that is that you can still share definitions between client & server while at the same time maintening a good old separation of concern.
All these new updates have highlighted all the benefits of using something else.
0:29 - That was MY source code that fundamentally misunderstands server actions!! I've never been so happy to nerd snipe someone and not only get personalized help but a YT video out of it! Incredible resource Theo, thank you so much for putting together this repo as it has already helped me grok server actions much better!
fine ill just use htmx
Just a few notes base on my recent dive into server actions. All data going into your server action doesn't have to be included in the form itself. You can pass in additional args through bind (e.g. . Also, and this is a bit of an ugly hack, you can force React to clear your form fields on revalidation by changing their keys. I do it by setting their key to performance.now() (e.g. ). No need to create a client component just for that. Additionally, I suggest you use redirect("/path") instead of revalidatePath("/path") at the end of your server actions because, when running with JS disabled, refreshing the page after submitting a form will cause it to submit again (old school webdev problems frfr).
I would like to see how we can write tests for this.
As I have a separate backend I won't be moving off tRPC anytime soon but even if I didn't, I have to say I still much prefer tRPC over the way they showed server actions directly in components, I like the client server separation. Throw in middleware, context and the other useful features that tRPC provides and I think it clearly offers a better DX than server actions do.
Big fan of server components but server actions, not so much
I have been using react for two years
I used redux, redux-toolkit, react query etc
But I didn’t used trpc because you could have to consume a backend different than NodeJs with typescript and it’s enough to use react query
Also I found “use-server” very confusing and not completely necessary, because we have easier to understand alternatives to do this.
The main advantage of using use-server is saving some lines of code and declaring types.
But do you think it is worth it to confuse an entire community for this purpose?
When you code not only T3 will read your code and will understand it, but other people will have to do it.
And trust me, is better to put things clear to other people.
I hope you are writing an OpenAPI Specification for your apis...
@@philheathslegalteam Im mainly front end developer, my coworkers take care about implementing swagger and openAPI specification
But I would do if needed :)
Although I wouldn’t use python or php for my side project backend, Trpc and T3 stack is completely perfect when you aren’t attached to a company
@@bules12 good stuff then its not problematic at all. OpenAPI typescript can make react query and SWR act the same way as tRPC with e2e typesafety.
Or if you’re just using raw react query you at least have the types clearly defined by the API
This makes php5 look good
Everyone was so gloom and doom about tRPC dying once RSC drops :) and turns out that tRPC is the perfect layer to call from your server actions even if you don't use client components from tRPC
Thank you Theo for mentioning next-safe-action!
Well, server actions looks good only if you plan to use your api on your nextjs project and nowhere else. The day another team will request you an access to an endpoint of your company from their tools, you will have to write a new backend for them lol
Same thing if you plan to code a mobile app one day, you will have to write a new backend ..
Right off the bat it feels so unintuitive to know that you had to structure things inside of a form. so many things implicit or abstracted in a way that feels easy to do things wrong
After installing create-t3-app, and watching your guide about T3 stack, this video is right what I needed!
You have shown how to use createCaller, server actions standalone, and with tRPC, which is very convenient!
Also, please explain, which pattern works best for you, which is you default approach between these 4 now?
I’ve been using the pattern for calling server actions from client components with startTransition and for me it’s the best one. Yes, sometimes I have to create the client components just for this but a lot of times my forms will include logic that calls for client components like client side validation, immediate feedback, etc.
For production use, avoid this quirks mode concoction and its older cousins, NextJS and server components, like the plague. With all due respect.
Do the performance benefits outweigh the added complexity? Maybe. I’m gonna fiddle with this in a side project to see if it’s worth using, but for production apps I still feel like I’m leaning towards client side for most complex use cases. I’ll probably throw in server components and actions for small simple forms or view only sections of the app
API security really isn't an irrelevant detail. Are those hidden fields in the closure replayable? Do they have perfect forward secrecy? Are there session-stealing style vulnerabilities here? Making the mechanism explicit makes it clear what trade-offs are being made.
If you care about being explicit with types, you definitely want to be explicit about the security properties of your system.
I think those encrypted input fields can't be decrypted, or else Next would have a problem on their hands.
I just use telefunc and no issues at all, this also comes at a benfits of getting rid of nextjs, trpc, tanstack query, etc that slow down everthing. Basically I use one that remove 3-4 other dependencies.
amazingly helpful demo! this needs to be in the next docs
No 'use server' - no confusion.
Super helpful video - thanks Theo! Sometimes, because of all the ways our minds have changed with TRPC, using createCaller still feels a little wrong, but this video helps justify it and the fact that I need to spend time doing the mental model shift.
I almost stormed out of the room with frustration watching your video but glad I stuck it out to the end. That last pattern is definitely the way forward. The other patterns are just DX when writing code around forms but ultimately terrible for reading/maintaining code
Thats fucking insane complicated, thank You for explaining.
when react used to be just a front ent library, everything was easier
Skill issue
New thing is more simple
@@kkebo no its dogshit now
awesome, thanks
we started using server actions just this week at my workplace
Naah, I'm not going to use this. Forget it
I am currently using the trpc client approach and I am having problems with refreshing page content. Could you do something on Next caching? I feel like there is no good way to invalidate a specific page other than the one you are currently on with the trpc client approach. For example imagine a page /editContent where an admin can edit a database entry which is displayed at /content. How would I inform the client, that its cache for /content is invalid? I would need to invalidate the cache for every client currently storing the old content of /content.
I am playing around with app router and all of its things for a while now, and it seems pretty magical. In a positive and a negative way.
If you understand how everything is intended to be used, you can really fly doing things.
But things are getting so implicit and are losing the self-explaining part that e.g. page router has, that it's hard to keep up to date, and master the thing.
I'm not even starting on how it must be like if you are working in a bigger team with engineers that are not as passionate as most of us are.
Nice options, I want to check more deep about that. I liked it, thanks :)
You can actually use async at the top level for the API createCaller logic, just await the creation of the context prior to passing it into the function and it seems to work just fine, since NextJS supports top level await.
Do you mean adding something like:
const user = await currentUser(); // e.g. Clerk's currentUser function
export const api = appRouter.createCaller({
db: db,
headers: headers(),
user: user,
});
?
Are you 100% certain that all of this code is run again and again per request, and not persisted across requests somehow (leading to different users using each other's sessions)? I have bad experiences with setting unscoped variables like this in Next, since it used to persist across requests in the pages router.
Interested to see how you'd get auth middleware with something like clerk working with trpc in server actions
I hate drizzle and prisma...raw sql is always more powerful😢
I totally appreciate the work you do to make these concepts clearer for all, but
The mess called js frameworks we're pushing is just absurd. This is discouraging beginners to get into web dev. Because of the millions of things we are pushing to be in this space, the moment you go back to edit a nextjs app you build last year November, you start seeing crazy errors and package updates with api changes and no other dev can make changes.
Very frustrating to find components without following the entire tree since they were moved up/down because of use client vs use server
sveltekit has server actions with much more simpler approach no headaches
Omg that side effect confused the crap out of me when suddenly I didn’t need formData in that separate file and everywhere the docs keep talking about forms…. I thought I had done something wrong lol
what about import server actions into a server component to act like a post route?
next-safe-actions package is the goat
Thank you!
Is that just next js or is that react implementation?
Because it would be very nice to have this "action" endpoint that has many action types automatically created easily outside of next.
By biggest fear is react just becoming next.
Really helpful video and I really like the last one!
I'm new to app router and I'm currently doing `Object.fromEntries(formData.entries())` for my server actions then parsing it with a zod schema of my expected shape. Any drawbacks to doing this?
This is the worlds greatest thumbnail.
Thanks Theo, great content as always! A video on Phoenix/Elixir Theo :)
I feel like you jumped through 15 hoops just to get this to kinda work. How is this "good DX"?????
This shit was the last straw before I quit Javascript. I converted from fullstack JS engineer to non-JS backend engineer and I'm never touching JS again unless I'm the one making the decisions. I'm getting too old to deal with the hyperactive JS monkeys "innovating" just because.
I'm still not clear on how SSR is better than Hybrid (SSR first, Hydrate after after), like, what's the downside of that approach?
The argument is that it's more efficient to split rendering between the client and server, instead of rendering everything on both. I'd argue that for the vast majority of projects, it isn't worth the effort.
@@heaps. I generally take the SSR-> hydrate into SPA approach since it sounds the lost sensible to me tbh. It keeos server load somewhat low (nice for me since I gotta pay that), devices are easily performant enaugh to hydrate quickly and make everything very fast and snappy... so the ssr-> hydrate spa sounds the best of all worlds with virtually no downsides to me... still (ofc not everything needs it and probably easier to implement solution would be suggested)
@@fischi9129 Agree on all points 👍
Was hoping to see a link to that taint video in the description 😪
I've seen that title changes...
Ok, the subscribe thing got me there hahahah
I'm new to nextjs so forgive me if this is a stupid question - but why does revalidatePath show the new content? docs seem to say it clears the cache, so it's not actually sending the new data to the client until they refresh, right?
Also, is it a reasonable mental model to think of it as the form sending a reference to the function to be called, that would have traditionally been called by a controller in express? So instead of hitting '/somepath' and having `Controller.doSomething()` run, the form just has the action `doSomething()`?
Anyway, love the videos 👍
*edit: oh, it's a closure not a reference?
@@nickwoodward819 And regarding your other question: When you write a server action, an endpoint is created on the server once you start it. When you call the action in your code, at runtime that endpoint is called. The form, when a user interacts with it on the client, has no access to the action you wrote because it lives on the server. It instead calls the endpoint associated with your action.
You mentioned closures in your edit: You are allowed to use closures in your server actions when writing them inside a component. Since the outside is React code, and it might live on the client, they needed a way to save that closure data. So they added a few encrypted, hidden inputs that are sent alongside the form data to the server action endpoint. This is the reason that if you define server actions in a component, you can only do that in forms (via the "action" prop) or buttons (via the "formAction" prop) inside a form.
This is my understanding up to now, at least. Hope that helps!
First reply got removed, presumably due to me posting links. Let's try again:
It's definitely not a stupid question. You're right, the docs don't explicitly state this in the revalidatePath or revalidateTags docs, which is where you expect them to state that. But other parts of the docs do in fact state it:
"Further, the browser does not need to refresh on form submission. In a single network roundtrip, Next.js can return both the updated UI and the refreshed data."
See the nextjs documentation at /docs/app/building-your-application/data-fetching/forms-and-mutations#revalidating-cached-data
And: "There are two ways you can invalidate the Full Route Cache: Revalidating Data: Revalidating the Data Cache, will in turn invalidate the Router Cache by re-rendering components on the server and caching the new render output."
See the nextjs documentation at /docs/app/building-your-application/caching#invalidation
11:30 that was funny haha
Very helpfull, thank you!!!
React has jumped the shark.
So react server is a less efficient version of what qwik is doing. I’m just gonna continue to avoid react like it’s the black plague.
I would call the server action directive "use another footgun". React is certainly pushing the community forward, but it relies on weak abstraction foundations like VDOM and useEffect and instead of working on those they keep on adding more stuff that is fragile and hard to make good. Looks like it is time to switch to Solid.js, it can also have server actions in future, after learning on react mistakes
So trpc will just become a simple api for using zod on inputs and outputs.
Nobody with react will ever use trpc as a client anymore, its just easier to call the server trpc method itself and a export this pretty async function using server actions.
man i could never get the nextjs hate it's literally the best thing that has happened to js world in all of it's existence
Are you getting paid? Because at this point - There's no point to make.
He's sponsored by vercel if you don't already know
11:30 lmao ok u got me good
I strongly dislike everything I've seen about server actions. They don't solve a problem that I have.
I'd love to see an example where going all-in on server actions makes sense, especially for teams with non-trivial codebases.
“Error: Viewer is not subscribed” 😹😹
Annoying that the context doesnt work with the callers, how do we protect mutations with trpc in the hybrid pattern then? If this is not possible, I'd call it more an anti-pattern.
It does. He just passed an empty object as context in this video
Ehh.. server actions = Server-Side useEffect.
It's not intuitive. Still hard to wrap your head around. This video demonstrates more Theo's masterful understanding of React and his ability to reason about it than it does to demonstrate easy server action implementation.
I appreciate the video because it truly helps. But I'm gonna call Server actions an L for now.
What's confusing about them, are people just dumb? It's just a code on the server you call, like you would write an endpoint and make a post request, but with this you don't need all the boilerplate, and can just use server actions
Exactly
this is content
So… it only took us twenty years to recreate Apache Struts?
Enjoyed the video, as usual. Not suuuuper into the aggressive "look at all this value I'm giving you, subscribe or you suck" bit. I'm subscribed, just find it very off-putting
The first one smells like webforms...
I don't understand the argument "it does not require JavaScript". What clients don't have JS nowadays?
❤
😡 all this is just frustrating. I won’t follow this. My structure is one rest api server (json) handles both web and mobile, web most logic is just view, fetch data from api server in json, if I need ssr I just pull data from the frontend server to api server for initial render, anyone can work on the api server without talking to frontend ever, frontend also never touches the db, everything pass via api server. Easy, simple, no bs
I am about to start working in a similar project with one restaurant api server. I’m probably going to use RSC to do the requests on the server for more performance in the initial rendering. But probably I’d skip server actions as they don’t make much sense in this scenario
Switching to Astro, Nexting next. Don't like where it's going, Very bad design choices.
I don't see the difference in the 4th action, you are basically using the "use-server" function in a different file. I've been using this for months as well. I don't want my server functions in the same file as the component
please please explain concurrent react!!!!!!!!!!!!!
Too much magic. Pls link me anything that makes sense of this. Is it making http calls under the hood? Webhooks ? Sockets?? So server actions is generating hidden api endpoints??
it's coupled AF
all I see is an inferior meteor.js
that use server string literal still is the most disgusting thing i have seen
Maybe I wasn't paying too much attention, but before watching this video I did not know what server actions are, and I still do not understand anything about them.
Your simplest vanilla example still somehow imports from `db`, `trpc`, `next/cache`, and `drizzle` and I don't know what any of these are!
Don't know about `db` because it's part of the repo you're showing so I did not see it before, the others - never heard of them. How could that be a simple example?
And then it becomes worse. React-query, Data Access Layer, `caller` pattern, "use server", "use-server" but it's in a file, not in a function...
Great error trick to get more subs!!! :)
Yeah RSC are trash, I am glad I am now practically 100% backend and I do not have to worry about keeping up-to-date with this shit React is pulling out.
God, JavaScript is such a failure. Watching video made my soul weep. What ever happened to KISS? I'll be sticking to using Vue, Svelte, and React with Go or Python in the back end
Please, just leave react for COMPLEX apps for client side...
This isn’t React. This is Next nonsense.
Javascript is a mess, we need a replacement for the web.
This is not javascript's shortcomings, it is React and the people behind it promoting the practice of building castles on sand.
wtf was that? at this point i'd rather use php
Server actions are just washed down HTMX. Prove me wrong :p.
stop trying to make RSC happen
it's not gonna happen
RSC patterns are infinitely better than what we had before.
Server ACTIONS are a whole different category of things. Important to have distinction
First
!= first
@@TheBuddillaconst third = “i’m”
Typecheck it
Use laravel, life gets simple.
I dont get why would anyone need trpc anymore? Even zod on backend? Server actions once exported from a file marked "use server" are fully typesafe and usable on both client and server components, its truly write once and use everywhere, couldn't be more simple. I integrated them with tanstack react query on client components and used it's methods for optimistic updates/revalidating data, passing the action as the fetch function.
Am I missing something?