Current section: Cookies 5 exercises

Implementing Cookies for Theme Selection

Loading solution


00:00 So actually, I'm going to take things a little differently than what I had you do in the exercise, because I want to kind of iteratively get to the point where we have this cookie happening. So we are going to go to our root. We're going to go to the action that's handling this form submission. And I'm going to add a set cookie header right here

00:18 that says set cookie, and the value is going to be theme equals dark, okay? And if I come over to my network, we clear this out and I click on this, then we're going to get a post request and we get this set cookie header right here, theme equals dark. If I look over here at my application now,

00:37 I'm going to have a theme is dark, cool. Okay, so what if we just say theme equals submission.value? And it looks like Copilot wants us to be HTTP only and same site lacks. Yeah, sure, let's do all of that as part of our cookie set. So now if I refresh and here, let's clear out the cookies. There we go, we have our CSRF cookie that's always going to show up there

00:57 because we've got that in our root loader. But now I click on this and we're going to get theme is object. Yeah, that's not what we want. Thanks anyway, Copilot. So the value is going to have a theme property. There we go, let's try that again. So refresh here, theme is dark. Awesome, that's looking pretty good.

01:17 Okay, so let's go over to our loader then and get the theme from that cookie value. So here we're going to get our cookie header is request. We're going to need that request from the loader. So request, this is data function ARDS and this is going to be request headers get cookie.

01:36 And ooh, now this is where things get a little bit tricky. Let's console log the cookie header. So we can take a look at what that is doing. We have theme equals dark and then our CSRF thing. So I mean, yeah, we can parse that ourselves. I do not recommend this. We're not going to end with this

01:56 but we can do a split on the semicolon. And here, yeah, let's say or empty string so that TypeScript's not mad at us. And sure, let's keep going with this, why not? So we've got our const, a theme header or a theme value.

02:17 And then we'll do a find, yep, where C includes theme. So this is going to be our, yeah, theme cookie. There we go. And then we can say dot split on the equal sign. There we go. And grab the first, yep, there we go. Now that's going to be our theme value.

02:36 Okay, so then we'll say theme equals theme value. All right, so let's come over here. We'll hit refresh and actually let's log it out so that we can take a look at what that value will be. So coming over to here, actually, heck,

02:55 let's just do data dot theme. There we go. And this is going to complain because it could be string or undefined. So we'll just say as theme and now everything's happy. Oh my word, look at that. It totally worked. And then we click on this.

03:11 Oh my goodness, ah, we have a working theme. How cool is that? Okay, so this is not our final form. Like this is not what I want this to actually look like. But I think it is pretty instructive for how all of this stuff works.

03:28 The idea is you set a cookie value in your action as part of your response. That response comes back to the browser and based on this funny syntax, it parses that out and sets that value according to these rules that we have. So we've got our path and we've got HTTP only, same site lax, all that stuff. And so it just stores it in the cookie

03:48 and then every request that it makes thereafter, like the request it makes to our loader, is going to have that cookie value. And so we can parse out, doing this terrible thing, we can parse out the value of that cookie and then pass it as our JSON to the client. The benefit of doing it this way

04:07 and making it HTTP only and all of that is that this will work on the server render. We definitely could in our component, we could say something like document.cookies and all that. And then this isn't really a private cookie or anything. We could totally make this not HTTP only, but by just doing it over HTTP only,

04:27 it kind of forces us into putting the loading of that cookie in our loader, which runs on the server. And so we get a server render of our theme, which is nice. So you'll notice with this approach, I can hit refresh and it server renders as dark mode. If I take a look at this, we'll find, yeah, it's right there, server rendered as dark mode, which is nice.

04:46 We don't have a flash of unstyled content. Now again, super duper, this is not what we want to end with. So let's clean all of this up and make sure that the app still works. We're gonna go to our theme.server and we're gonna do all of, like many of the same things that we were doing before,

05:04 except this time we're going to use a proper cookie module for parsing things for us. So let's come over here and say, get the cookie header from the request. So this is the stuff that we're doing right here, this nonsense, yeah, we're not gonna do that. So starting here, we're gonna say, whoops,

05:23 our const cookie header equals request headers get cookie. And then we're gonna get, if the cookie header exists, then we want to parse it. Otherwise we don't want to parse it at all. So we'll just say cookie header. If that exists, then we're gonna parse it. Otherwise we'll default to light.

05:44 That's our fallback for our website. And if the cookie header is null, so basically if it's null, we're gonna return the default, which is light. What we're going to do though, is say if the parsed value, so here, let's call this parsed.

06:03 And the parsed value is light or the parsed value is dark, then we can return the parsed value. Otherwise we'll return our default of light. And this is complaining because we're getting a object here.

06:22 So this ends up being an object of the different possible parsed values of the different cookies that we can have. So we actually need to have a cookie name here. So this will be dot theme. What I'm going to do actually is we're gonna say const cookie name equals theme.

06:42 So that's a particular cookie. We could also do a CSRF, right? Because we've got a CSRF cookie in here. So this is parsing all the cookies. We just want the theme one. And I'm gonna say cookie name right here because we're gonna want to use that same cookie name when we set the theme. So extracting it to a variable kind of helps with that. Okay, let's just stop right there

07:02 and make sure that it will continue to work if we do this. So we'll say get theme from the request. And that get theme is gonna come from our theme server. Then we can get rid of this nonsense and that and save that. And let's make sure that this is still working. Ta-da, woo-hoo, it's still working, good.

07:20 All right, so loading the cookie value is working as desired. And also, we could get rid of all of our cookies and make sure that we start on light mode. If I switch it to dark mode and then say let's get rid of all these, refresh, it defaults to light mode. So we're all good. Okay, so setting the theme,

07:41 that's our stuff that we're doing in the action right here. We're gonna call that function there. We're gonna serialize it so we don't have to manually construct this string anymore. We're just going to serialize it using the cookie module. So this is actually a little bit easier than what we were doing with get theme.

07:59 We simply return cookie.serialize and we pass the cookie name, which is theme, and then we pass the theme value and then set the path to slash. And that is the only config that we really care to set right now. We could also say HTTP only

08:16 and various other, same site and secure, all that stuff. We're not gonna get to that right now. We might do some of that later. With a theme, it doesn't actually really need to be private anyway, so it's fine. Okay, so then we can say set theme. That's coming from our utils that we just wrote. And submission value dot theme.

08:35 Ta-da! And that, that is that. Let's make sure that it still works. Refresh, do, do, do, do, do. It looks so great. You did awesome on this one. Good job, pat yourself on the back. This is sweet. So we've got a fully server renderable theme value,

08:55 all working within our remix action to set that cookie. And so we're not talking to a database or anything unless you consider the cookie storage to be a database, which yes, maybe sort of a little bit. So we're just, the request is coming in and we're saying, hey, here's your response. It worked. You need to set this cookie value.

09:14 And then in our loader right here, we're saying, hey, grab that cookie value and convert it into a theme. So if it is a valid theme of part light or dark, then return that valid theme. Otherwise, we'll default to light. And it's awesome. So well done. We're not going to get into actually setting this

09:34 to be a system theme. That would be an extra credit thing that you can do if you wanna spend a little extra time on it. But we've got a pretty good solid start for this. So well done.