STOP using useState, instead put state in URL (in React & Next.js)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to talk about keeping your state in the URL instead of using use state in react so when I Google something let's say react jobs you can see here in the URL Google is adding something and this is called a query string and I can also get search results in a particular time frame so I'm currently in Poland so it's all polish but when you filter for a particular time frame you will get another Edition here to the query string and you will see the same on many e-commerce websites as well for example here on the new for sale e-commerce template website on the product page we have colors and sizes if I click on the black color you can see something is added to the URL if I click on the large size we can see that this query string now has become even bigger now why would you want to do this well there are many benefits to doing this users can share this URL on chat or social media and the person that they send this to can copy that link can open it up and they can get the exact same view they can see the exact same color and the exact same size that you picked a person can also bookmark the euro well right so in browsers I can bookmark here I can come back to this later and I get the exact same view or UI that I have right now which is much faster than if I would bookmark just just general URL and then I would have to remember what options I picked to get the same UI now I can just bookmark this one and get the exact same UI users can then also use the back button so if I try something else for example maybe I try a different color or a different size and I think oh no the previous one looked better I can just use the back button and it will go back to the previous UI or maybe the forward button oh no I want to go back again and now you can use the forward button and sometimes you want to open up the URL in a new tab or new window so I can just copy that paste it and get the exact same UI maybe your app is a bit slow maybe something broke and you just want to refresh hit refresh and I get the exact same UI sometimes you have tech savvy users and they can manipulate the URL to get exactly what they want instead of interacting directly with your UI so here I may know that white is a particular option and I can just use it it's also good for SEO search engine optimization so Google can recognize that you have different views for this URL and may rank that appropriately in the search rankings sometimes a user just wants to save the URL for themselves not bookmark it but maybe they want to send it to themselves through email or they want to put it in a note-taking app to come back later sometimes the user wants to open it up on a new device maybe they were browsing on their mobile and they want to open it up on desktop they just have to send the URL to themselves and they can open it up and these days we also have server components in react and xjs and if you use use state in react it has to become a clients component however if you lift up the state to the URL it can actually stay a server component so for this tutorial I want to walk through an example and I have replicated the for sale e-commerce template so here we have a t-shirt product page and it's going to have three different colors so we have black white and blue and it has five sizes so I have two constants for those I have color variants and I have size variants then on this product page I just set the default selected color to Black and the default selected size to medium and then what we have in here on the left side we're gonna have this image so I have three different image URLs so if the selected color is black we use image URLs I have to find that up here is not important but black will automatically give me this URL here why it will give me the other URL and so on so this will show the appropriate image for each color and then these actual filters here we have color and we have those three color variants so I'm just mapping over them and creating a button for each one so we have three buttons here for black white and blue let's see they have a key they have some styling here so if they are the selected color so here I'm going to check selected color the default one here I have defined as black right selected color is black as the default one so if that black is actually the one that we're mapping over then that one will get a blue border right so the selected variants will have a blue border now here I want to uppercase the first character so I have to do some JavaScript magic here just taking the first character uppercasing it and then connect it with the rest of the string arise with them for sizes I'm doing the exact same thing I'm just mapping over each size variant creating a button for each one we have a key some styling if this selected size for example MD is the default one if that is the one that we're currently mapping over we're going to add a blue border otherwise just a gray border and I'm uppercasing all of them each character so I made medium the default one so selected size here is medium but now what should happen if I click s or white if I currently click on these buttons nothing happens right this is completely static right now so now what we could do is we could use use state to deal this state right so instead of hard coding select this color to always be black or selected size to always be medium now we're going to manage that with use that let me comment this out we're going to say selected color now is going to be a state variable so I'm going to use U States here I'm using line wrapping so it wraps onto this part here but it's part of the same line and this is the default value for you state let's just make that black and when I save here actually we get an issue because I'm using your state and that's only pass possible in the client components so let me convert this into a client's component I'm using next.js here so I'm saving here and that should get rid of the error so now we should also create one for selected sites we'll have the default be medium so then I can remove these hard-coded variables and now we should get the same result so now when I click still nothing happens because we are not using the setter function yet of course when we click one of these buttons we should invoke a Setter function so when we click on any of these buttons for example let's say the color buttons we want to set the color to that color that we clicked on I already get the suggestion so I'm just going to accept this one so when we click this function runs and it will just set the color to the color that we're mapping over so it could be white blue black so if I save now if I now click on white you can see the the Border changes as well as the image because this will set the color to let's see it will set the selected color to white which will re-render everything so it's going to change the image here and then also here for color variants the selected color is now white so it's the white button that gets that middle border let's do the same for the selected Sciences so when we click on any of these buttons we can set the selected size to that size so if I save here now if I click on the other buttons you can see it changes so now we are changing the UI with use State the problem with this is we don't get any of those benefits right now so now if I want to share this with somebody else let's say I want to know hey what's your opinion on this white shirt in XS size I won't be able to share that but now if I share this URL and send it to somebody else and they're going to open it up like this so now they're going to open up like this and they're going to see a black and medium a UI now whereas I want to get their opinion on white and extra small but they're gonna see black and medium and now let's say I want to bookmark this if I would bookmark this and come back to this it's basically just like a refresh I would see black and medium instead of that white color and now I think oh I want to see the previous one I prefer the previous one the back button won't work here and the forward button neither Etc so we want to put this state in the URL now so whenever we make a change here you could think oh well we're going to use use effect because whenever one of these selected options changes we want to synchronize with some external system the external system here being the URL right the URL lives outside react and in react we have use effect to synchronize with something outside react so here we can say use effect and you could say whenever those selected options change we want to do something here with the URL let me import this like this so whenever these change we also want to put that in the URL now and actually the browsers they give us the so-called history API to interact with the URL so what you could do is you could push this so you could say window.history dot push state for example and the first argument here is going to be null then we have a weird empty string here for historical purposes and then we can update the URL here so we could say the color needs to be selected color and size is going to be selected size so this entire thing is called a query string it has query parameters so here here you could say this is one query parameter this is another one and they're separated by this Ampersand and the whole query string is separated from the rest of the URL with this question mark here so if I save here and now when I click on white you can see this URL here has updated let me make this a little bit wider you can see now we have color as white and size is medium here in the URL when I click on blue the color changes to Blue when I change the size it also updates so now if I refresh you can see it doesn't work yet just goes back to color black and sizes medium the default values we have so this is just pushing it to the URL but we also need to read that from the URL when we come back to it later and you could do something with that in use effect as well and that's how many beginners would continue the problem that you're going to run into is now you're keeping the selected color both in your state here as well as in the URL so you basically have two sources of Truth Now that you need to accurately synchronize that's the first problem here and another problem is we are using this native solution from browsers but if you're using a framework like next to ask you already have some solution out of the box that's just going to be a better option to work with these URLs so to achieve the same with the next.js router here we can say constant router we're going to user router here from next.js and I'm using the next CS app directory so make sure you are importing this from next navigation then I can use that here instantiate it here essentially and then I can say router.push and here it's going to be the same string now next to us now we are navigating programmatically and next we'll automatically scroll to the top of the page if you navigate so here we have a second argument where we can undo that because here when we click we don't want to scroll to the top so we can say scroll is false now I also need to add the router here to the dependency array now if I save here and let me just undo all of this for clean slate we're going to get the default values here that's fine but now if I click you can see it still works and I'm using the solution from next to S this is recommended because this is also also integrated with for example the link component so you have one standard solution for all of your navigation instead of going around there with window history but now the problem is of course if I go to the back button this doesn't work yet right so here this is just pushing it to the URL we're just adding to the URL we're updating the URL now whenever we make a change here but of course when we come back to this URL we also need to read from the URL now and we could try doing that here as well there is also a native browser solution to read these search params from the URL and that's called window.location.search so with this you can read this search parameters right so again this entire thing is called a query string a query string consists of query parameters so you could say that this one thing is a query param or parameter this size is another query parameter or query param they are separated with this Ampersand and the whole query string is separated from the rest of the URL with this question mark so people will refer to this as a query string or query parameters or even search parameters now any URL you also have path parameters so here in this URL I have forward slash product and then forward slash t-shirt you could say that's a path parameter it's part of the path and then after the question mark you have the query string so we could use the native browser solution to read the data from the URL but next.js also helps us out with reading we have something called use search params in client components and this will give you the search parameters in the URL now right now you can see it starts to become messy because we are trying to synchronize here ourselves with use effect we have use State here we now also have user router and this becomes a very messy setup very quickly and the reason is essentially that we're trying to keep track of it in two ways now we have our own use State and then we also have the state in the URL so two sources of truth and that's not what you want you want one source of Truth so we need to make a decision here which one we keep and of course we're gonna keep the state in the URL so let's remove all of this now from you state and all of this use effect as well and we're going to just treat the state in the URL as the one source of Truth so I can even get rid of you state use effect on all of these Imports here now we get an error it's saying selected color is not defined so now how do we get this selected color from the URL copilot wants to give me use date again but that's not what we're going to use now so we can use a hook from next.js it's called use search params Let Me input this from next navigation not the react router done from next navigation and this will give us the search params from the URL so the selected color we can then use search params.get and then it's the color parameter so if we do this I press name here that error is gone and then we can duplicate this for the selected size search params.get for size so now if I save here you can see we actually get white and small here which is the same same as in the URL now if I change the color to Black in the URL you can see we get the right color if I change the size to XL and the color to Blue if I go there you can see we got the right UI here because we can just read this from the URL and this is data that the browser will give us we don't need to use use stats now what happens if I click black here if I now click on any of these buttons I'm going to get an error because now we're only reading from the URL but now we also need to update the URL properly and here we're still using that on click Handler with setting the color in the use state so I get these errors so we could use the router again and do router.push that's how you programmatically can add something to the URL with next.js but next.js actually provides you something else that you can actually also use here which is simply the link components right so this is used for navigation and if you click on that next.js will update the URL it will manage all of that URL state for you as well it will just add that so here we can just specify an href so we can say eight draft is going to be a query string and let's see so color is going to become whatever the color is that we're mapping over here right so this is for color variant so if I click black here to become black otherwise it should become White and the size should stay the same right so we're going to click black the size should still stay this Excel the selected size so we can say size is simply going to be selected size so if I save here I do need to import the link component of course so then let me save here and now if I click on any of these color buttons you can see the URL is updated and because the URL updates and we are using search parameter it will re-render our component so we get the new search params and we get the new selected color right we get black here and so all of this UI here will be properly updated so let's do the same for the sides here instead of a button we will just simply use this next link and the href here let's see if copilot can copilot knows what we want to do here so I'm going to save here right so I'm going to click on any of these sizes the color should stay the same so that should still be that selected color that we already have the size should become the size that we are currently mapping so here now if I click medium you can see it properly updates here and I get a strange error here so let me just refresh here for a clean slide I still get an error here because I have this on click I should just remove that that was from the use State solution that we had before so now let me refresh here we have black and sizes large so that's working now if I update the color it works if I update the size everything is working now so now I can send this to somebody else I can ask what do you think of this white shirt in XL format that version is going to open it up and they're gonna see this the exact same UI that I was looking at let me close this let me close this tab as well and also now when I click around here and I'm like now maybe the blue one was better so now I can go back I can navigate through the choices that I was looking at with back and forward buttons I can open it up in a new tab or new window maybe I was browsing on mobile want to open it up on desktop I can send it to myself I can bookmark it and come back to it my bookmarking you essentially just refreshing and you can see we get the exact same UI and we get all of those other benefits that I mentioned at the start of this video now one other cool thing is this can actually stay a server component so here we're using use search params so this is all managed client side and so this needs to become a client's component but you can also get access to these search parameters on the server so if I remove this and I even remove the use client now so now this is a server component I can remove this so on the server you actually get that as props so here you get search params as a prop and then the syntax is a bit different here so now it's not this get method to get the color it's just a property itself on that search params object so we get size like this now if I save here this is now a server component and if I refresh here you can see it still works the exact same everything is still working and it's a server component now instead of a client's component now I'm getting red squiggly lines here from typescript so typically you do want to type your props type for search params I'm getting this from the next s documentation so it's a bit of a complicated type here but and this is what that would look like now there are some other important things that you need to be aware of so maybe somebody is sending me this and I'm going to go look at through some options and now I want to go back to let's say the chat I have to go through all of these options that I just looked through because now with link it's the same as programmatically pushing to that route so with that router that we saw before you can do router.push this will actually add a so-called entry into your history your history of URLs so then when you use back and forward you have to go through each of those entries that's what you get with the link components if that's not suitable for your use case you can also use replace replacing will not add an entry to that history set of entries so you will immediately go back to that page another thing to be aware of is that some people may actually change the url so they may change this to let's say purple that's a color that doesn't exist there so now we get selected color is purple and we don't have an image for purple so we don't see an image and it may cause other issues as well you may want to validate the data that you get from the URL but for example zot or some other schema validator people may actually also remove this from the URL so you may also want to have some default values so here dot color is nothing so here we can also say or black or let's say medium so now when you go here you will actually see some default State another important thing to be aware of is that the URL is always a string and sometimes you're gonna have strange characters that need to be so called URL encoded so here when we set the URL usually you want to be a bit careful because let's say the color has some colon in the name right maybe we have black and this is from some collection from the fall let's say black from the fall so now if I save here and I try to add this to the URL you gonna have this colon and you may have other characters in the URL here this is just an example let me undo this so typically you want to encode these properly for the URL and the browser helps you out here so instead of specifying the href like this you may want to do it as follows so you still have this and then for the actual query params you can use new URL search perhaps and here that's a function so you pass that and it expects an object here you can specify for each query param what the value should be so color should be color or you can just write color in JavaScript if you have the same name there and size should still be selected size and I'm missing a curly brace here so this is a safer way of updating the URL now I do get an issue here from typescript and I think it's because here where we get the selected size selected size here the type is going to be a string or array of strings so here it may actually be an array of strings and it's telling us hey you cannot assign an array of strings here so it needs to be be actually a string so here when we get it from the URL we know it's not going to be an array you may want to validate this more thoroughly but here of course you can actually assert that's going to be a string I do need to use these parentheses here otherwise it won't work so let me also do that for the other one so here is just going to be a single string and that should get rid of that issue yeah so now when I click here in the color it still works it still properly updates if I refresh we still get the correct data here so if I do blue it still gets the correct color and we can do the same for the size see just replace this and here color should take the already selected color and size should become whatever we are mapping over here and we can just leave that off in JavaScript so now if I just refresh here and I click around everything is still working as it should right so this is really useful so whenever you have some kind of detail page such as here in e-commerce product page or search results page or like a data table another good use case or even something like a modal in the open or closing State you can put that state in the URL treat the state in the URL as the single source of Truth you can make it a client component that can even stay a server component and you get all of those benefits so it can have filter parameters you can also do it for sorting or pagination or for search queries all sorts of data can be put in the URL and you get all of these benefits that we saw at the beginning of the video so I hope this was helpful hope that you learned something my react next to escort is coming out soon make sure you subscribed on the email list to get a notification and a discount make sure you've mastered the fundamentals both JavaScript as well as CSS I have courses on them both check out the links in the description thanks for watching and I hope to see the next one bye
Info
Channel: ByteGrad
Views: 104,496
Rating: undefined out of 5
Keywords:
Id: ukpgxEemXsk
Channel Id: undefined
Length: 21min 40sec (1300 seconds)
Published: Mon Sep 11 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.