TanStack liberates developers from Next.js’s rigid server-first architecture by making server components a granular choice rather than a mandatory overhaul. It is a refreshing return to a client-first mindset that prioritizes flexibility over framework dogma.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
This is WAY better than NextJS (TanStack Server Components)Added:
React server components. Love them or hate them seems mostly hate these days.
But that might be about to change as Tanstack has entered the game. That's right. We now have Tanstack server components and they've taken quite a different approach from Next.js. Let's take a look.
Now I'll start with a paragraph from their announcement post that I think will put a lot of people at ease. It says most people now think of React server components in a server first way.
The server owns the tree. Use client marks the interactive parts and the framework conventions decide how the whole thing fits together. This turns React server components from a useful primitive into a thing your whole app has to orbit. We do not think you should have to buy into that whole model up front just to get the value out of React server components. Essentially what they're saying is they don't want to go down the Nex.js route where it's server components by default and then you need the use client directive where you want to have interactivity. Instead, Tanstack wants to think of it as what if you could use React server components as granularly as you could fetch JSON on the client. With that goal in mind, then let's take a look at how they actually implemented server components because spoiler alert, I really like the way they did it. What I have here is a normal Tanstack star application. So everything at the moment is going to be a client component. And the only thing I've done is some small install steps that you need to get server components running, which essentially just installing some packages and modifying your V config. This is what the page currently looks like. We have our greeting component here which obviously currently a client component and in the code it literally is just a single react component. Then down here we have a normal tanstack route and we're using the greeting component here. Now let's say in our greeting component you wanted to do some logic on the server. In my case I want to get the operating system host name then also some environment variables that are only available to the server just to show you that this is actually running there. At the moment if I try and use os.hostname it's not going to work since this is a node function and it's not available in the browser.
What we need to do then is take our greeting component and render this on the server. And the first step to doing that in tanstack start is with a simple server function. As you can see, I've got one here called get greeting. And all we're doing inside of here is using the new render server component function, putting our component inside of it, and returning the renderable server component that we get back. You can think of this as simple as we're creating a get request for our component. Next, then all we need to do is simply fetch the component from the server function that we created. And we can do that inside of the loader on a route here. So we're just awaiting get greeting and then returning that as well. And it's still a renderable server component. Then we can use that inside of our route here by using loader data.
And we just use the component down here like this. With that, we now have our first tanstack server component. You can see os.hostname is now working. And it's also pulling in environment variables that are only available on the server.
Now the thing that I absolutely love about this implementation is if you notice the only new thing in here is the render server component function. The rest of this was just normal tanstack start. You could replace this with just some simple JSON data being returned and you'd fetch it in the exact same way. I also think this implementation is just really explicit about where your code is actually running. You do it all inside of a server function. So, it's pretty clear that's going to be run on the server and also inside of the render server component. In fact, I think I can improve my demo code here by simply taking the functions that we're running up here that I want to run on the server, putting them inside of the server function, and then simply pass that values into my greeting component as props. So now my greeting component is essentially just a bare component that could actually be used on the client or the server. And I'm running all of the logic that I want to run on the server inside of my server function here. Again, it's pretty explicit.
That's going to be running on the server. This literally feels like the exact opposite of the logic used in Nex.js and I absolutely love it. It means I can think of React in a normal way. It's all client first, then add in server components on top when I want them. But what if I wanted to use a client component inside of my server component? So nested within the tree.
Say I wanted to add on a counter button here that each time we click it just adds to the counter. Or if I simply try and add this into my server component here with an on click and then also a use state call. You can see it completely breaks. It says use state is not a function or its return value is not iterable. That's because greeting is being used as a server component. We can't use this client functionality. To fix this you have two options. And the second option is definitely the best one to use. But the first option is going to feel familiar to those of you that have used Nex.js. We can simply move that logic into its own component and then use the use client directive. This works in tanstack start server components. We can simply just use the component inside of the server component now. And as you can see, it is all working nicely. The downside of this approach though is that we now have a server component controlling the rendering of a client component. And this can start to get a little bit messy. Aka, if I wanted to find out where my counter component was in the tree, I would go to my route here and see that we have a greeting server component. Then go back up to the greeting server component. and inside of the server component see that we have a client component and this mess can really start to add up and just make that boundary of server and client become a little bit unclear. Tanstack wouldn't settle for that though. They asked themselves what if the server did not need to decide every client-shaped part of the UI at all. And this led them to create something entirely new composite components. To use one, the first thing I'll do is remove our client component from our server component. And I'll simply replace it with any children of our greeting component. Next, we also need to change what we're returning from our server function here. Instead of returning a renderable server component, we need to return what's called a composite source. To do that, we can use our second Tanstack server component helper function. Create composite component. In here, we're essentially just building out a component where props here are considered the slots. I'm just using a very simple children slot.
So, it's going to pass through anything that we put as a child of my composite component into this props. I'm passing through to the greeting component that we just had. With that again, what we need to do is simply fetch our composite component from our server function. And we do that in the exact same way in the loader here. And you see I'm just renaming source to greeting. Then I'm loading it with the use loader data. The only difference here though is we can't use this as a component. You see it's throwing an error here. To actually render a composite component, we need to use the composite component helper component that we get from tanstack server components. And as the source prop, we pass through the composite component that we fetch from our server function that we created earlier. With that, my server component is now rendering in like we had before. And I'm also passing through the counter as children of this composite component.
And that is getting passed to the greeting where we had it set up here.
So, it's passing it through into the props. So, everything is now working nicely. I can also go into my counter component and remove the directive that we had here since that is no longer needed since it knows this is going to be a client component as it's inside of a composite component. This is being used as a slot. Now, it might seem like we got the exact same result there, but with more work than just using the use client directive. But the power is really coming from the developer experience, and it's a bit of a switch from the use client model. Instead of having our server decide where our client components render in, like when we had the counter component inside of the server component itself, instead, what we're doing with composite components is saying, "Hey, there's going to be a slot here. We're going to render in a client component." But the server component itself has no idea what that's going to be. We add that in later in our client code. So we handle all client-based components within client code itself. That's only the beginning too. If we take a look at a more complex page like this post one where this post is being server rendered. There are two issues that I want to solve. The first one is that I want to add in some actions like liking the post and following the author. But I want to add them in above the title here and I want to use a client component. At the moment I'm simply using this children slot pattern. That means if I added in my post actions down here it would just go where the comments are since this is how we have the component set up. So, I want some way to tell my server component where to put specific client components.
Then we have a second issue of if I do have a follow author button. At the moment, this post page actually has no idea who the post author is. We actually offloaded all of that logic into the server component itself. If I wanted to get the author in a client component down here, I would actually have to fetch the JSON for the post and get the author that way. And that's not really a great pattern. We'd be double fetching the data. Lucky for us then, Tanstack actually has two other slot types that we can use on a composite component besides this children one. And the first one is going to be render props. This is essentially just any prop that is a function that returns a React element.
So this can be called anything. It doesn't have to be called render actions. And here I'm just saying what data I want the server component to pass through. That is going to be the post ID and author ID. Now all we need to do in our composite component is simply use this function that we're passing through as a prop wherever we want the component that's eventually going to be rendered to be. In my case, I want that to be underneath the card header. So, I can call it with props.nder actions. We can use an optional. So, if it's not passed through, it doesn't break. It just won't render in. Then, we can also pass through the information that we want from the server component to our client component. After this, our composite component is going to accept the render actions prop that we just created. And for the value, we simply pass through a function which has a post ID and author ID as the argument, which the server is going to fill in. Then, we simply render in our post actions client component, and we can pass that data through as the props. So now I have a button up here where I can like and copy the link to the post and also click on follow author here where it's aware of the author name despite the fact that I've actually never fetched it on this page. I only fetch it in the server component and the server component is passing that data into the client component for me. Now you might think this breaks the logic that we had before where we said we don't want any server components to be in charge of rendering client ones, but it doesn't. And that's because slots are actually opaque. The server component up here has no idea what's inside of this.
It just knows that something goes here and that needs to pass through these values which in this case is the post ID and author ID. This function doesn't run on the server. Instead, the server simply sees that it needs to pass data through. And then down in our client, this is when the function is actually run and the component is rendered in.
The exact same thing also applies to our third slot type which is component props. This one is actually a little more simple than the render props. All we're doing is instead of having a function which then returns our client component, we're just passing through the client component as a prop itself.
Then on our composite component definition up here, we're saying that we want to accept a prop which is a React component that has the props of post ID and author ID. Then we can use this within the component itself. You can think of component props like a placeholder. The server component knows there is going to be a component there that needs some data. In our case, the post ID and author ID, but doesn't really care what that component is as long as it accepts those props. So, if I changed my post actions component down here to another one that I've made called fake post actions and then we save that, you can see that this is still going to render in because it's the client that's responsible for rendering this component. It's only the server that provides the data. Looking at the documentation, it doesn't seem like there's any real difference in which approach you take whether you go with component props or render props. It might just come down to preference. The only difference that I can see is that maybe you want to modify the data that you get from the server. So in this case, we can do whatever we want with post ID and author ID since it's just a function and then we can pass that on to our component. Whereas if you're using component props, you just pass through the component itself and the server handles passing through the props. Now that's the basics of Tanstack server components. But there's still so much more to like. For example, if you wanted most of your page to be server rendered, maybe you have a header component, content component, and a footer one, and you want them all server rendered, you don't have to bundle them all into one render server component function. You can actually use promise to all split them out into three different functions and then simply return them as an object from a single server function. But what if one of those components takes long to load? That would mean the entire server function would and therefore the entire page would. Well, don't worry there either. What we can actually do is instead of awaiting the render server component function, we can actually return the promise that it creates. Then on the client, we can take advantage of the use hook and suspense boundaries to load in skeletons. So server components will just load in when they're ready. I just really like the approach that Tanstack has taken here. It doesn't feel intrusive. I'm not forced to adopt it and I can adopt it without any weird workarounds. Plus, when I do actually go to use it, the server components themselves are actually only three new functions. The rest of it is just simple Tanstack start server functions, something that I was already using, and it's as simple as fetching data. This also means that it integrates nicely with tools like Tanstack query, something that I will definitely be doing. And it also makes things like caching simpler. If you wanted to, you could literally just cache the response of the get request on your CDN. I'm definitely going to be exploring these more, so let me know in the comments below what you think of them and if you'd like to see more videos on them.
While you're there, subscribe. And as always, see you in the next one.
Related Videos
VALORANT's Latest 'Exclusive' Tier Bundle is Rough...
KangaValorant
17K views•2026-05-28
Flight Attendant Mocks Poor Looking Black Woman — Mid Air Announcement Exposes Her Real Power
SkyboundStories-b4r
184 views•2026-05-28
I FIXED My Friend’s Blown Turbo RX-8… Then Sold It
Cameron-RX8
134 views•2026-05-28
NewsWatch 12 at 5: Top Stories
NewsWatch12
1K views•2026-05-28
Simon Jordan & Danny Murphy deliver PREDICTIONS for Arsenal's Champions League FINAL with PSG
talkSPORTArsenal
6K views•2026-05-28
Botting is OUT OF CONTROL in Classic WoW (Again)...
SolheimGaming
108 views•2026-05-28
The "AI Job Apocalypse" is CANCELLED!
WesRoth
9K views•2026-05-28
STREET FIGHTER 6 - INGRID Story Walkthrough @ 4K 60ᶠᵖˢ ✔
RajmanGamingHD
12K views•2026-05-28











