Remix Fundamentals

Progressive Enhancement Solution

Kent C. Dodds

Kent C. Dodds

Professional Trainer
Remix Fundamentals

Check out a free preview of the full Remix Fundamentals course

The "Progressive Enhancement Solution" Lesson is part of the full, Remix Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Kent walks through the solution to the progressive enhancement exercise.


Transcript from the "Progressive Enhancement Solution" Lesson

>> How many of you finished that one? Did we have time? Okay, cool, yeah, I thought it was relatively quick, there was just lots to read. So one of the things in this exercise six is progressive enhancement. One of the things that I wanted to draw home is that everything we've done so far doesn't need client-side JavaScript at all.

So, in the background here, I encouraged you to go to the root.tsx, which we have not looked at so far. But this is your component that's responsible for rendering everything between the opening HTML and the closing HTML. So if something doesn't show up in the body of your HTML, it's your fault, because you're the one who's rendering that, remix doesn't touch that.

Remix does give you some components that you can render that are built into the compiler and everything. But yeah, you're the one rendering it. So if you don't want JavaScript on the client, then you just get rid of it, you're gonna comment out the scripts. And because remix is server-rendered, then the entire app still works.

I can still go to post, I can go, let's not slow this down, we don't need that for right now. I can go to the homepage, I can go to the login, all of this. You'll just notice we're doing full page refreshes between these, but the app works.

That's what progressive enhancement is about, a foundation of a functional app, right? And so many apps today do not function without client-side JavaScript. Now, there are some apps where you could argue that they probably would be impossible to work without JavaScript. And you're probably thinking of Figma maybe as a good example.

And well, yes, technically, that probably wouldn't work very well without client-side JavaScript. It actually is possible, let me see if I can find it really quick. Jjenzz, yep, nope. There it is. So Jenna has done a lot of really cool stuff with remix, and she built a Figma that works without client-side JavaScript.

I don't know if I would actually wanna use this to design anything, but the point is that you can actually start with a foundation of something that works for most apps. How many here building Figma? I didn't think so. So most of our apps can mostly work without JavaScript, and then we use JavaScript to make it better.

And I'm not just talking about navigating around these different pages, I'm actually talking about the full experience, even mutations, New Post, new-post-yo, This is new, I keep doing that, new. And dude, totally created. Now, I can go to my post page, and there's my new post, and there it is.

Whole thing works, no JavaScript necessary. So that's what we've done so far. There are a couple of reasons why this is cool. First of all, I would say, most people probably don't mind having JavaScript on the page. Most of the time, that JavaScript is gonna load, most of the time, the user hasn't disabled JavaScript.

So ability to work without JavaScript by itself is not all that interesting to me. Especially, since the user experience isn't the best, you're getting full page refreshes and loading more data than you maybe need and stuff like that, because you're reloading the HTML over and over. So that part's not what is cool to me.

The cool thing to me is that now that I do have JavaScript on the page, I can go to post-admin and I can go create new post. And whether or not I have JavaScript on the page, if I'm on a slow 3G network, and here, let's disable the cache.

And let's say that I'm just working on a really slow network, as soon as this HTML loads, that really slow network. I hit Create Post, and my JavaScript's still downloading, but I was able to hit Create Post and the whole thing still worked. So as important as it is for us to make our initial page loads fast, and hydration runs quick and all, reduce the amount of JavaScript that we're loading on the browser, that all is important.

But it becomes a little less important when your app actually can still function before the JavaScript finishes loading. Because we code split so efficiently and everything, you're actually probably not loading a silly amount of JavaScript anyway. And yeah, but it becomes less of a problem. So that's one thing that I like a lot, it works before the JavaScript finishes loading.

But even better than that, what I love about the no JavaScript functionality or support, the progressive enhancement support of remix, is that it is the proof that you don't need application state management to build a remix app. So, I've told you that and I've said that, and maybe you believe me, hopefully you believe me, I don't know, don't just believe me, you should test it out for yourself.

But this is my evidence that we can build a full application that works without JavaScript. So how could you possibly say that you need a state management library for it? If it works without JavaScript clearly, there's no state management. So I think that's pretty cool. There you go, that's evidence.

No JavaScript necessary means that there's no state management necessary, which is half of the code that you write. So you can get a lot more done. And that's what happened with my side, I was building this, I was not planning on user accounts. I was not planning on the call Kent podcast, where you can literally record a call in your browser, and then I get that recording, and I can respond with my own recording, and we get that stuck together in a podcast episode.

I was not planning on doing that, but I'm like, well, I finished a little faster than I was expecting, so let's see how far I can take this thing. And eventually, I think maybe I'll turn this thing into [LAUGH] a business, cuz it's pretty cool. Would you pay three bucks a month for that?

I don't know, maybe. And so many things I was not planning on doing, the blog post recommendations at the bottom of every one of these blog posts. You get a recommendation to three other blog posts that are related to what you're reading, something you've never read before at least recently, and some other random thing that's popular post.

It's different every time, you refresh the page, it's gonna be different. I just like a lot of different ideas, like, wow, look at all these cool thing I can do on top of what I've already done just because I don't have to worry about application state management. So it makes me so much more productive.

So no wonder I joined the team, because I'm like, this is all I wanna do now, because I love this thing a lot. Okay, so hopefully, that point makes sense. So we worked before the JavaScript loads, we work without the JavaScript, so why do we have JavaScript? What's the point?

Why do we put JavaScript on the page? Because we can make the user experience better, we can enhance it with JavaScript. It is not enabled by JavaScript, it's enhanced by JavaScript, and the enhancements that you can make are great. And the mental model is as simple as full page refresh on every navigation, but the capabilities are what our users are expecting, and that is what makes this so awesome.

So with JavaScript enabled, and if we slow this down as a slow 3G network, I hit Create Post. And we see that there's a network request going on, but the user gets no feedback whatsoever when they click on that. Well, sort of, it kind of messes up, because when I click Create post, then the focus, it makes it look like something's happening, nothing's happening.

There's no feedback for the user that a request is being made. Without JavaScript, if I go Disable JavaScript, we actually have a better user experience. So what Disable JavaScript does is it rejects all JavaScript scripts that you're trying to load, so the browser doesn't load any of those.

So we don't have any JavaScript on the page. If I click Create Post now, we at least get a favicon spinning. So, what we've done by not thinking about pending UI is we progressively enhance with JavaScript to a worse experience. What's the opposite of enhancement? I don't know, it's like we've dehanced [LAUGH] our experience with JavaScript, that's nonsense.

And of course, none of you would ever do that, I know, you'd never make a worse experience, you'd always think about penning UI, and so that's what we're going to do. We'll go into our app > routes > posts > admin > and new. And in here, this is all client-side stuff, so we've taken care of the backend, that's all done.

All we have to do is on the client, we need to know when the user has made a submission so that we can say, hey, we're creating, this thing is happening. And because remix is the one managing that fetch request for us, it's the one where we're gonna get the information about transitions that are going on.

Now, transitions are not just for posting or submitting a form, this is anytime you transition between different routes, okay? So we're gonna get transition from useTransition. And again, it's not React, it is remix-run/react. And by the way, I should mention, like I said, we will probably change that.

And if we do, of course, we'll probably support the old version or whatever. So we don't break your stuff or we'll have a code mod or whatever, but in the repo, I made this file. And so if eventually that does ship and that changes, I will add that note to the changelog.

So hi, folks watching in the future, just check that changelog to see whether that piece has changed as well as like the file system routes and stuff. Okay, so now we have the transition, the transition is gonna tell us some stuff about where we're going and what what's happening, what is causing this transition.

So we're gonna get our isCreating state from, nice try, compiler. But actually, transition has a submission. It may or may not have a submission, if we're just clicking on a link, there's no submission there. The user is not submitting any data, they're just clicking on a link. But if they're submitting a form, that is going to have a submission.

And so we're gonna just say, we're creating if the transition has a submission, so we'll just booleanify that thing. I know some of you are probably like, why didn't you just not note that thing? I'm like, you got to be honest. Is this more simple than just Booleaning it?

I don't know, a double bang, I don't know. I mean, if you wanna save your keystrokes, that's fine with me. But okay, so now we know that whether we're in a creating state based on whether there's a transition. So our designer just said, hey, just disabled the button and update the text content for the button, we don't have a loading spinner for you.

But you could render a loading spinner, you do whatever you want to, have a little bar that goes across the top, because you can actually use this anywhere in your app. I could put this in the route of my app and have a global bar. You do whatever you want, because there's only one transition that can happen at a time.

You can't submit multiple forms at once, and we'll talk about that in the advanced remix workshop. But for these navigation based transitions, you can only navigate to one place at a time. Even if you submit over there and you're like, never mind, I'm submitting over there, you no longer have that old one, right?

So there's only one transition, that's why this is global, and you can have it anywhere. Okay, so we'll take this as creating, and we're gonna say disabled if we are in isCreating state. And then if we're isCreating, then Creating..., otherwise, Create Post. And that's it, put it on.

So yeah, okay, I'm still on slow 3G, that's good. So waiting for the JavaScript to finish loading here. I don't wanna wait, that's rattling. Okay, now, throttle slow 3G, and I say, well, whatever, I don't care. We hit Create Post, we get Creating.... So now, we have progressively enhanced to a better experience, we're not doing a full page reload and all of that nonsense.

We are staying on the page, we're doing a fetch request, but we've hooked into remix, so remix can tell us the navigation that's going on, which is a form submission so we can say creating. And that was the exercise, there's the extra credit. That's slightly different topic, but it was not a lot of code changes but a fair bit of concepts, hopefully, it all made sense.

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