Intermediate Next.js

Server Actions Q&A

Scott Moss

Scott Moss

Superfilter AI
Intermediate Next.js

Check out a free preview of the full Intermediate Next.js course

The "Server Actions Q&A" Lesson is part of the full, Intermediate Next.js course featured in this preview video. Here's what you'd learn in this lesson:

Scott spends a few minutes answering questions about server actions. Questions include mixing tRPC and server actions and suspense vs. useTransition in React 19.


Transcript from the "Server Actions Q&A" Lesson

>> Student: So I have a question, when using TRPC, how would you combine the two of those together?
>> Scott Moss: That's a great question. So, it's tough [LAUGH], because I'm doing that in production. And the question you just asked me is something I ask myself every single day, how do I do this?

Why am I doing this? I'll just tell you how I'm doing it.
>> Student: Okay.
>> Scott Moss: And you can decide if it's valuable for you. So what we do is, let's pick a page, I'll pick this page here, okay? So here, I have the data, right? This is literally what I do on my app, I do an initial request.

I'll get the user, I'll get the initial data for this. I'll immediately do something like this. I'll have something here that's home. This is the actual home right here. And this is gonna be from components, slash, the actual home component. That's not what I call it, but you get the point.

And then there's nothing here. There's absolutely nothing here. And what I do instead, is I'll say actual home, and I'll pass in that data. So whatever data I got here, I'm passing it directly in here. So in this case, it'll be that. This component is a client component.

It's a client component that takes this prop. And in the case of TRPC, which uses react-query, in that hook where you do the use-query, or in TRPC's case, it's trpc.the-name-of-your-query.use-query or something like that, you can pass the options object that says initial data. Which is like, what is the initial data for this query?

Before it even makes the query, I pass this into it. So what I'm doing is I'm making sure whatever my server component queries, returns the exact same thing that the TRPC query in here would return. So I can just populate the TRPC's cache with whatever the initial render of this is.

And then from there, it's all TRPC, whether it's mutations, whether it's queries, it's all just TRPC. I don't use what I just showed you guys.
>> Student: Got it.
>> Scott Moss: For a few reasons. I didn't know how to do it when I first made the app. [LAUGH] That's the biggest one.

Two, it's just a lot more work, in my opinion. Right now, when it comes to things that are very hyperactive, are hyper interactive, so polling, infinite scrolling, WebSockets, things like that. It's just a lot harder to do in this world of caching, mutating, invalidating the cache. That process is just a lot more to think about, the more interactive your app becomes.

But when it's a form, or a simple create like we just did, yeah, pretty simple. So because of that, we don't want everyone on the team to be an expert on when to make that decision. We just decided just use TRPC for everything because that works. It's fine, it's not that big of a deal.

And also, we're an app, we're a dashboard, it doesn't really matter. But if we were more of a static site with some interaction, I would probably lean towards more doing all the server-side stuff. Because if I'm New York Times, I'm not doing TRPC, I'm doing this, because this is all server-side.

TRPC is very client-side, it's very heavy. That's gonna be slow on people's phones, compared to doing something server-side. Whereas none of that JavaScript gets loaded up because it's all on a server. So it really just depends on the experience, I think. What's the relationship between useTransition and suspense, or is there one?

I don't think they have any relation. I don't think there's any relation between what a transition does and what suspense does. Because you don't have to use a promise inside of a transition. You can do whatever you want. A transition is just saying, this is something that normally affects the UI, which typically is a state change or something like that, and I don't want it to, that doesn't have to be asynchronous.

A suspense is like, here's a promise, I want to wait for this promise to resolve. In the meantime, show this thing, that's a suspense, and that is more of something to do with network layer. It's more aware of what's actually happening, it's more purposefully built. startTransition is a generic function that just opts you out of locking down the UI.

The best way I can describe it is request animation frame for state. That's the best way I can describe it, request animation frame. If you don't know what that is, it's like, you would use that to make your animation smooth. Do that 60 milliseconds to get 60 frames per second, it's like that, but for state.

So that's the best way I can describe it. But right now, Next.js is using, and it's not their fault, React just came out with this. And it has a useTransition, but now you can do async things. So now you can't await that. So we can't do that right now.

So earlier, when I was like, yeah, you probably want to be able to, where was it? Here, I was like, you probably want to be able to return this and get the results of it to do something. Well, we can't in our current implementation, because I can't await this in a transition.

Where's that happening now? As far as I know, this is not async yet, unless they updated it, I don't think it is. And if it is, I haven't used it yet. So I don't feel comfortable teaching it, but I do feel comfortable talking about it, and this is what's coming.

You can async to startTransmission, you can await a promise, and you can get whatever you want back, and you can do all the things here. So I think that closes the loop for a lot of things as well. These are the things that I'm talking about that makes it a lot easier to use this technique now, this cache server-side query, bust the cache.

Now, these are cool, cuz I'm inside of a client component, this is a client component. I'm using a server mutation, a server action, and I'm getting the result right back here for my client. I can bound it to a state, so now my JSX can see it. Yeah, this kind of closes the loop, right?

So this does a lot of things for you, as far as being able to use this without having to go through all these hoops. So it's getting better, but, like I said, Next.js was waiting on React to do a lot of these things. I really like the approach that they're taking.

They're like, we just want to make what React is doing easier, but we're not gonna introduce all this crazy stuff to you guys. We're just gonna build opinions on the foundations that they built. And I think that's the great way to do it. But sometimes that just means Next.js ends up releasing things super early, and people are just like, what's going on?

But reality is, they can't do anything, they have to wait until React fix this stuff.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now