Turn Progressive Enhancement up to 11
Feel free to check out the Epic Stack example to dive into the code.
00:00 We've got this really cool image uploader, so I can drag and drop an image, and we get a preview of that, and you can upload it. It looks awesome. The way that works is with this onChange. So when we change the file that's selected on this input, which is what happens when you drag and drop an image, or if we click on it and select an image from the file chooser here, then that also triggers the non-change. In either case, we create a file reader, we read that image, and then set the preview image to that, and then our preview image is fed into this image tag.
02:30 So it's not the way we wanna do this at all. Instead, we're gonna follow what Jenna has suggested here with a document body class list as a script tag in our root. So we're gonna go to our root and right down here in our document, right in our head, we're gonna say scripts. And because this is React, we're going to say dangerously sent inner HTML, and here's our HTML, is this string of HTML that's going to say document, and instead of adding it to the body, I'm going to add it to the class list right here. And here it's saying remove nojs.
03:06 We're going to actually add hasjs, just like she has suggested in here. And so now we can come over here and If we take a look at our elements, we can see hasJS is not added, and that's because we do not hasJS. But if I turn this off and refresh, boom, now we hasJS. So that's awesome. And now if we take a look at this, we go over to some CSS and we do some CSS magic to make things look a little differently.
03:35 Let's bring that CSS in and now we have JS and so those that CSS doesn't apply everything works as expected but if we don't have see JS then this is going to load And there's no flash of the different state or anything like that because this script evaluates before the rest of the HTML document shows up. And so we're able to say, hey, let's add this hasJS right up here. And then it continues to parse the rest of the HTML of our document. So, we know whether we have JS or not before the CSS is even loaded, before the components or the HTML for the components are even loaded. So there's not going to be any flash of any kind.
05:05 And we're going to get ourselves actually two problems. One is we have a nonce requirement because we've got a content security policy that requires the nonce. So that's easy enough to solve. There we go. Refresh that.
05:19 Boom. Now it's gone. No problem there. But then we've got a hydration error. So this hydration error is saying, hey, on the server, you rendered the light hful overflow x hidden hasjs.
05:32 And then on the client, it didn't have that. And so what's interesting about that though is here we're rendering this and it's never going to have hasjs the way that we have it written. If we run this on the client it's always going to miss that class name. The reason it's saying the server sent us that is because this hasjs gets added before the hydration happens. And so React is assuming, well, I mean, if it's showing up before I hydrate, I'm the first thing that's supposed to happen.
06:01 It must have come from the server. So the error mess is actually a little bit incorrect. If we would take a look at the view source on this, we're going to see this is what came from the server. It does not have hasjs. But because React sees that class name before hydration, it assumes it came from the server.
06:19 In any case, we're in trouble, because we need to make sure that the server does not send hasjs, because that's like the entire crux of how this works. But then secondly, that the client has hasjs. So we need to know like based on whether or not we have information from the client, we need to know whether we should have hasjs. So what if we do this? Hasjs equals type of document, it's not equal to undefined.
06:49 Okay, so that actually this is more like is server or is client so we maybe we could call that and then we'd say is client then has JS otherwise we don't know so we'll just leave it as an empty string. Now this is a bit of a, honestly a bit of a hack, but it's a pretty safe hack because it's going to ensure that the HTML that is served from the server is what we need it to be, but also it ensures that the HTML that's hydrated by the time React shows up is also what it needs to be. And so it's a pretty safe hack. I'm okay leaving things the way that we have it here. And so now we have gotten rid of our hydration warnings.
07:33 And the actual problems that come with hydration warnings is not just we're putting a band-aid on the problem. No, we don't have warnings. Hey, no. Like, those hydration warnings actually mean React is behaving differently. You need to get rid of the hydration warnings.
08:18 You make sure you handle any hydration issues. And then you can use CSS to style things differently based on the experience that is available to the users that you've got. And you can give the users the best possible user experience based on that. So I hope that is helpful to you. Have a wonderful day.