Kent and our panelists dive deep on the hottest new React framework: Remix. What it does today, what makes it special, how it lured Kent away from a lucrative independent teaching career, and what’s coming up next.
Kent C. Dodds: Yeah, yeah. So we don’t run it necessarily as a single request. I mean, on a client transition I think we do… But we run them all in parallel. So every one of your route modules can export a loader, and when a user navigates to a different page, or if they just land on a page, then we run everything in parallel. So you cannot access your parent loader data, because if we allowed you to do that, then we would run into this data cascade, which is not good at all.
So yeah, every single loader runs in parallel. We do not have this problem… And I guess I’ll fill in the silence and talk about forms. [laughs] So loading data is an interesting thing, but making changes to data is what really makes the difference between a website and a web app. I mean, the distinction between a website and a web app is kind of silly anyway, but a lot of people will, I guess, say that; I don’t know, I don’t care what the difference is. You can build web apps with Remix, you can build websites… I don’t care. But mutating data is often the missing piece in most frameworks. Most frameworks are like, “Yeah, okay, we have a really nice API for loading the data. Oh, but you’re gonna change something? You’re on your own. You’ve gotta figure out how to update the data when you make a change”, or whatever. So we’ll bring in these different libraries that know nothing about your routes, and you have to wire everything together.
So Remix says “No. That’s a very important part of the web. Since Web 1.0 we had forms for mutating data, and we’re gonna do that again.” So Remix gives you a really nice API for data mutations that is just a form. And when you load data, you use your loader; when you mutate data, it uses your action. So you have this form, it automatically posts to the route that you’re currently on, and so just like with the loader, when you’re writing your component, you’re like “Oh, I need more data. I’ll just scroll up the file to my loader, make some changes on the server-side”, and then boom, I can use it. If you’re writing a form, you can just scroll up to your action function, and now you can handle what happens when a user submits a form. And this, again, only runs on the server, so you can do all your validation logic there, and whatever; you can share validation logic if you want to… So if you wanna run some validation logic on the client, you just literally take the validation logic, put it in the function and use it in both places. Like, in the same file. So it’s pretty straightforward to do that.
[40:07] And then you can, again, use your private keys, connect to databases, whatever, because it’s just on the server… But then to take it even further, Remix kind of takes cues from Web 1.0, where if a user submits a form twice in a row - so like they hit Submit, and then they… You know, we’re checking off a to-do list, or whatever; check, check, check… What the web browser does before we bring in any JavaScript, the web browser will say “Forum submission is a navigation, so we’re gonna go and we’re gonna wait for the server to respond”, and then the user says “Go again” - they actually cancel that request. So they ignore whatever response that was, and they’ll send a new one. And boom-boom-boom, you can send and cancel. And Remix does exactly this same thing.
And also, when the server finally does respond, the browser is going to render whatever HTML the server responded with, or if the server is doing things right, they’re gonna redirect the user somewhere else, so they can go and get that. So what that effectively is - we say hey, all of the data on the page is completely up to date, because we just barely got it all from the server. Remix does the same thing. By default, when you make a mutation, Remix says “Who knows what changed on the server?” Nobody knows. Not even the developer sometimes. “So we’re just gonna go refetch everything.” So what this means is by default you never have to think about keeping state up to date. You don’t have to worry about application state at all. That’s why I said you don’t need Redux, or anything like that, because as soon as the user makes a mutation, Remix will go ahead and update all of the state that’s on the page.
Now, of course, you can optimize that. There might be some unnecessary data fetching happening. But the default is correct. And I think that is really, really powerful. And on top of that, because we build web apps, not every single mutation is a navigation necessarily, so we have really nice APIs for non-navigation mutations, but they operate in effectively the same way. So this drastically simplifies a lot of what most people are building on the web these days when it comes to mutations. And even people who used to write web apps like 6-7 years ago are singing the praises of like “Oh my gosh, this feels just like it did before.” And then the people who are building modern websites, or who – sorry, I should say that differently. The people who have just started learning building websites in the modern world are like “Wow, this is a totally new approach. Using a form instead of a button with an on click? Wow, that is interesting.” But it all works really well… And on top of that, it also works even before the JavaScript has finished loading. So we load it faster, and if the user happens to start using your app before it’s finished loading, it actually still works. So progressive enhancement is coming back. We’re making a come-back with progressive enhancement. This is really a big win for the web. So… That’s exciting for me.