React Server Components (RSCs) are a new way to partially render your react application on the server! This is really cool because it means you can use the file system, any node package, or even call an API right from an "async component".
An even cooler property of RSCs is the you can next server components inside of client components. So potentially you could have a react tree that looks something like this:
When react does the "server" part of rendering each server component will be rendered and will create somewhat of a "bundle". This bundles contains the output of the "async component".
Say you have a Badge
component that displays the latest commit has of the repo.
When this runs at build time it will run the shell command and return the component to render in the application. Pretty sweet!
You might think that's enough to reason about RSCs, but you're wrong!
In the above app what if we instead had this:
This doesn't actually work because the ClientComponent
is not a server component and client components cannot render server components.
...but didn't I just say the opposite? Not quite!
While a client component itself cannot render a server component, it can be passed a server component as a prop.
The reason the first App
works is because we use ClientComponent
's children
prop to pass the server component to the client component.
Then the client component can choose to render it or not!
Component composition for the win!
For the website you're currently on I wanted to have a "post preview" when you hovered over a link to another post hosted on this website.
My posts are written in MDX and rendered with @next/mdx
.
This handles the "bundling" of the MDX files into RSCs.
If I rendered the preview RSCs within the client component I would get an error. I assume this was happening because the "bundle" I mentioned above was required to happen at "build time" and I was trying to do it at "run time".
Try hovering the following link to see it in action.
Here is how the PostPreview
component works:
And here is how I use it: