Remix Fundamentals

Data Loading Q&A

Kent C. Dodds

Kent C. Dodds

Professional Trainer
Remix Fundamentals

Check out a free preview of the full Remix Fundamentals course

The "Data Loading Q&A" Lesson is part of the full, Remix Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Kent answers student questions regarding what Remix is doing when making a request from the loader to the browser, if this type of loader handles serializable JSON, when the HTML is received, and if data can be transmitted other ways like CSV or YAML.


Transcript from the "Data Loading Q&A" Lesson

>> It's unclear how a request is made to the loader from the browser what is Remix doing behind the scene exactly?
>> Yeah, let's talk about that, so, if I load the page initially you'll see there actually no fetch requests made here. And that's because this is all server rendered.

All of the content of the HTML here, if you go to view source, then you're gonna look at my first post, just shows up right in there. You'll actually notice that this also shows up. In a second place in here, this is for hydration. So, in react when all the JavaScript shows up in the client, we need to run all of the React components.

So, we set up event handlers and context and all of this stuff. And so, to be able to render this component on the client, we need to have the data that's gonna come back when you call useLoaderData. And so, that data shows up in JSON that is embedded in the content of the document.

All of that is managed for you automatically by Remix. It's on this fancy double underscore variable that is on window. That Remix just grabs, and sticks into the Remix context so it can grab that when it hydrates your app. So, you won't get a fetch request when you land on the page.

But if you navigate to the page, then you will. So, if I go back to the homepage and go to blog posts, then I'm going to see this fetch request right here to get all that data. Because we're not doing full page reloads between these pages, we're gonna do a client side transition and so Remix says, okay, you're going over there, let me go grab the data for that.

So that it's ready by the time we render this component. And so, this is actually fairly different from the way that I used to build react apps. Where normally, I would navigate instantly, show a loading spinner while I go get the data. With Remix, the user says hey I want to navigate, Remix says, okay, hold that thought let me go get the stuff and then we'll render.

And these are trade offs here and Remix gives you levers to switch that to like be able to navigate instantly and show a spinner if that's what you want. And that we'll discuss in the advanced Remix workshop. But yeah, I think that the default makes more sense. It actually resembles the way that the web is as well.

So, if you're on, here's actually a good example of that. If I want to go to my profile page, I click on this. I'm sticking around here. Nothing's changing until I actually that page is loaded, right? So, Remix again, it's a browser emulator, just doing the same thing that the browser would do.

>> This type of loader handle what is serializable JSON?
>> Yeah, thank you for asking. That's a great question. So, what if we had a post date on here? Okay, so now, if I come over here and I say, we're going to also say date.tolocaltime, whatever, right.

That's not working, and the reason it's not working is because post date is a string but I literally just set it to a date and in fact when I'm on the server side that is a date. That's exactly what it is, so what gives TypeScript to Remix combo, what's up?

Well, JSON does not support the date type and also doesn't support undefined, it doesn't support like a whole host of other like regex, a whole bunch of things of functions, all that stuff. And so, yes, the answer to the question is the use loader data generic does handle non serializable types and it will serialize those so that you will not have a type error when you say like to local times or whatever that thing that function is called.

Yeah, thank you Copilot. So, yes that is that. Now, some of you are probably maybe a little let down by that you're like well, I kinda wanted to preserve those types across the network boundary. So, there are projects out there that allow you to preserve those types where they provide their own hooks.

Add their own JSON, where it will serialize it in a special format and then it will deserialize it to get all of those, those actual same types. If you want to use those be my guest, personally what I like to do is if I need something to be, especially with dates, if I need that to be formatted in a certain way.

If your server is on a different time zone from your user then you can end up in funny situation or not just different time zone but do like, desires a different format or something. You can end up with a situation where the server formats this way and then the client formats it this way you get a flash.

And so, I always like to do all the formatting on the server. Just format it there, if you want to care about the user's preferences then give them away to specify those preferences and have your server reference those. So, but again, long winded Kent over here answering questions too long.

>> When you navigate to the post page, you get just a data object back. When do you get like the HTML that's rendering the list? Is that when you first visited the site, or how does that work?
>> Yeah, so, when you navigate or when you land on the page, you get all the HTML.

When you navigate to the page, you just get the, let's clear all this out so we can see that, you'll get just the data. You'll also notice you get the JavaScript. So, this is the react components that are coming in here to generate what ends up being the DOM here.

>> Can we transmit data any other way like CSV or YAML or text?
>> Yeah, so, you can absolutely like read CSV files or YAML files or whatever in your loader. If you want to get that data into your loader, into your component via use loader data that's got to be JSON at the end of the day.

So, you can convert it to JSON or whatever. If you want to have some sort of endpoint in your app that serves up a CSV like you are generating a report or something, then you can totally do that. We are not going to get into this today but it is a subject called resource routes and basically you can make a resource route like that.

You just don't export a default component and now it's a JSON API. Which is pretty rad and then from there you can actually say, I want my content type to be a PDF or I wanna generate an image or whatever you want to, the world is your oyster.

And so, yes, the answer to your question is, yes, you can do that. I can not think of a situation where you would want to use loader data to return a CSV. More likely, you would want it to return maybe a string, right, of what the CSV is, and you could totally do that.

It would just ultimately, it's gonna be serialized into JSON and then deserialized. Yeah.
>> So, is a loader pretty much an API endpoint?
>> Yes, yeah. So, no, creating API endpoints in this directory and then having some indirection through a fetch call or whatever. It's literally just this and yes, it is 100% in an API endpoint.

I don't advise this but you could click on this and now you have the URL to get the data for this route. So, you could copy that and boom now you've got your API endpoint, like I said, don't do this, if you really need an API endpoint, just make resource routes like I showed earlier.

But, yeah, each one of these is its own API endpoint that Remix handles calling for you.
>> Is used loader data effectively binding the JSON to a template and how does Remix know what part of the tree to update?
>> Yeah, so, use loader data and the loader for the component or for the route where the component appears, yes, they are bound together.

And so, you're effectively taking saying here's my data, here's my template, squish them together and I have my HTML and my doc.
>> So, yeah that's maybe a way to think about it it knows what part of the tree to update because it manages all of this. We'll get into this a little bit here but if we cd into exercise or two, npx remix routes, then this will go through the Remix convention for your file system and it shows you the routes that are in your app currently.

And so, it says, here's our index route, here's the file for that index, or yeah, here's our post route, it's an index file. And here's the file for that. And so, it knows which part of the tree to update based on which module is responsible for that loader and that component.

And so, it only will update this part of the tree it knows it doesn't need to bother with this part or anything else. Basically, magic is the answer.
>> The last question is, is there a use case for using a generic type of anything other than type of loader and use older data and if not why not build that type and by default?

>> Yeah, great question so unfortunately, just doing that is impossible from a TypeScript standpoint. There's no way for TypeScript to know that this load us loader data should be referencing those. That's kind of a runtime thing. So, it would be really cool if that were possible but no, that is just not possible with TypeScript.

So, yes, you will have this as your basically the keys you have to type [LAUGH] every time you need to access voter data.

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