Current section: Server Components 27 exercises
solution

RSCs

Loading solution

Transcript

00:00 Let's start out on the server side. We'll come over here to our server app JS, and we're going to switch from returning JSON right here to returning a render to pipeable stream. Let's get rid of this entirely. I'm going to rename this to props.

00:16 We're also going to update this to be from API to RSC, so that we communicate through the name of our API, what to expect. Then we want to pass these props over to our app. If we take a look at our index right here, you'll notice we're calling app with all these props. I'm actually literally going to copy

00:36 this and move it back over here. Now you can almost visually see what the code is doing. We're moving our app into our server. We're moving our rendering, our UI creation is moving over to our server. Now, to be clear, RSCs don't actually require a server.

00:54 This could be something that happens at build time, which technically a build server, it is still server. But a lot of people are concerned that, oh, RSCs mean that you need a server. Not necessarily, but to take advantage of RSCs to the fullest, you are going to want to be running a server.

01:12 That's always been that way with everything. It's the best opportunity is available if you are running a server. But yeah, here we're going to import the app components. Now we're going to take the UI elements that are created from this and pass it to render to pipeable stream. So render to pipeable stream.

01:31 This wants it to come from React DOM server. I'm going to hit tab just so I get that completion, but we don't want it to come from React DOM server. Instead, we're going to have it coming from React server DOM ESM. Now, this package is a special package that you'll notice that in our package JSON,

01:48 we're importing it from the MyTemp deployed version of this package because that package isn't actually published to NPM. So we can import it like this, but it actually is technically not published to the NPM registry because this is just a thing

02:06 that is missing so many optimizations, you shouldn't actually do this in production. But for our learning purposes, it's awesome. While I'm up here, I'm going to grab these couple imports that we want. Right down here now, those props are what we're going to go right there.

02:24 Here we go. Then this is going to give me an object, a stream if you will, but I'm going to pluck off just one property and that's pipe. This should actually be pretty familiar to anybody who has worked with server rendering before, because you've got your render to pipeable stream and you're piping things.

02:43 So what we need to do is we need to pipe the results. So as the bits are coming through, we need to send all of those to the outgoing response that is part of the Hano context here. Then we'll just let Hano know that, hey, we're going to stream the response. So the response is already sent,

03:02 we're streaming it through this pipe here. This bit right here, that's all just Hano.js stuff, and so that's why it was just given to us. But now, our server is ready to go. So if I come up here and say slash RSE,

03:21 then it is going to blow up. Actually, the reason it blows up is because there's one thing we haven't done yet. So if we come over here and we take a look at the error, it's going to say, hey, this import failed. There's no import render to pipeable stream found in this module.

03:38 So sorry, you're going to have to do something better. If we dive into our node modules and go to React server DOM ESM and look at the package JSON, then we can find our exports config right here. Exports, and there is a special export for slash server.

03:58 So the default export is going to go to this server file. But if we're in a React server condition in that context, then we'll get the server node. So let's take a look at the file that's right next to this one, the server.js. This is the one that we're trying to import. That's actually going to give us an error if

04:17 we properly evaluated that. But thanks to our ESM environment, that looks like that's not even evaluating. But it's saying the React server writer cannot be used outside a React server environment. You must configure your node using the conditions React server flag. Okay, well, we can do that. So coming back over to our package JSON,

04:37 let's update our dev script to add the conditions. Then we'll restart our application in the workshop app here. And then I hit refresh, and would you look at that? We've got some RSC content. I'm loving it, I guess. Yeah, this is super.

04:56 So this RSC content, you can feel free to inspect it, use that tool to get an understanding of what this RSC content actually looks like, or at least parse it a little bit. But yeah, we are in a good place as far as our server is concerned. Definitely not a good place as far as our app is concerned, though,

05:14 because now we can't make that request to API. We get a 404 for that because we deleted that. So let's go over to our UI and update this. So app is now coming from RSC, so we can delete this. We'll no longer be importing the app file. You'll notice over here in our network,

05:33 if we look for app.js, there's that import right there. And if I save this, we do a refresh, that's no longer showing up. So we've moved all of that code over to the server. And let's pull in create from fetch from react-server-dom-esm-client. If I save this and refresh, then we're going to get a new error

05:52 because we can't resolve that package. So that's because our imports aren't configured. So let's go over to our index.html. And we'll stick that in our configuration here. Make sure that it's proper JSON. Don't forget any commas.

06:09 And that way we're importing react-server-dom-esm from the proper location, specifically the client import. So now when we import this, it's going to come from esm.sh properly. We can take a look at the network and make sure that react-server-dom, there it is, it's right in there. Perfect.

06:29 Okay, great, so now we can import our stuff. And we're not importing our other stuff properly, that app component. So let's be a little bit more specific about this promise name. So we're going to rename it to initial-content-promise because we're not fetching data anymore. We're now fetching content, some UI. And we're also not fetching it from the API endpoint anymore.

06:49 We're fetching this from RSC. And then we don't, because it's no longer JSON that's coming back, like, does that look like JSON to you? Well, yes, it kind of does, but it's delimited by lines and it has multiple segments and things. So it's not proper JSON. So we're not going to parse it as JSON.

07:08 And in fact, it's going to stream in over time too. So that wouldn't, we don't want to wait for that to happen. Okay, so we're going to create an initial-content-promise. And we're going to pass the initial-content-fetch-promise into create-from-fetch. So this is going to take that RSC content

07:25 and convert it into UI elements that we can use. And I meant use in the literal sense because we're going to use that right there. And this is going to get us our content. It's no longer getting us the data. Now it's the rendered content in that RSC format. So once it passes through here,

07:45 it goes from the RSC format into React elements. So just for funsies, let's add a console.log content and we'll also return the content. And let's see what things look like now. Refresh, huh? Yeah, that thing's totally working. Let's look at our console. Would you look at that? That looks just like regular React elements, doesn't it?

08:07 Amazing. Yeah, we've been here before, right? This is pretty cool. Yeah, this is pretty neat. So we've got our locations. We've got our initial location. We pass that to our fetch request so that our ship ID and all of those details show up for our server

08:26 because we are still getting the ship and all of that data, but we're just calling up props now, passing that directly to the app component on the server side, and then passing that into render to pipeable stream, which will generate the React elements, that RSC payload. We pipe that into the outgoing response and then on the client side, we can consume that

08:45 using create from fetch. That will convert the streamed response into React elements, which then we get that in the content and we return that content. It's not magic, it's just JavaScript, but it's pretty cool. The other thing I'll just make sure to call out again is this conditions React server

09:03 allows us to run React in a special environment. In fact, we looked at react-server.msm, but let's also take a look at our node modules, React and package.json, and you'll find these exports have our react.react-server, and so this is a special type of file.

09:21 If we go to, yeah, it's gonna be react.react-server. There it is. This is gonna go into our CGS, so let's dive into that. React, react-server. We'll look at development because I don't wanna look at minified code, and if you dove into this, then you might be able to find a number of things

09:40 that are not supported, and I am assuming that there would actually be some useful errors that are gonna be thrown in the event of trying to call useState, so let's look for useState, see if we can find anything. Nope, that's not gonna be in here at all. So somewhere there's going to be a place where React is gonna give you an error

10:00 for trying to do something that you're not allowed to do on the server. So yeah, here's a use memo. Interesting, so yeah. Feel free to dive into there. Invalid hook called. Oh, yeah, there's our, hooks can only be called in the body of a bunch. Yeah, okay. I think we've dove, divvied into that enough.

10:19 So it is important to run our RSC server in this special context. Your bundler is going to be doing this, whatever framework you're using is going to handle this for you, but this is an important aspect of what's going on is that you're going to get a special version of React in all of your components

10:38 that are running in that RSC context. And we'll talk about that a little bit more when we get into the client component discussion later. And so, yeah, when we rendered a pipeable stream, that app is running in that special context, it pipes to the client, and then the client consumes that with createFromFetch, and we get React elements to render.

10:58 Pretty nifty, I should say.