Nuxt 3 Fundamentals

Query Params

Ben Hong

Ben Hong

Nuxt 3 Fundamentals

Check out a free preview of the full Nuxt 3 Fundamentals course

The "Query Params" Lesson is part of the full, Nuxt 3 Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Ben creates a reactive property to filter the to-do list based on a query parameter passed in the URL. A the differences between the onMounted and onCreated lifecycle methods are also discussed in this lesson.


Transcript from the "Query Params" Lesson

>> So the thing about using the use route composable is that it provides more than just the parameters, it provides you the ability to basically see what exactly you can get from the route path. And this can be extremely helpful when you start passing query parameters. So an example of this is when if we go to the navbar, and let's say we wanted to add another link.

And this time it won't just be two todos, it'll have a question mark, which is basically how you start your parameters. And we'll say, completed, right? And so to say, completed equals true. And you can imagine then from this URL what this would expect is when you get to the to do list, that you would actually then you would only fetch the completed items, you won't actually see the incomplete ones.

So how might we accomplish that? Well, first thing first is we're gonna go in here, and as we take a look at this though, I'm starting to realize that, wait a second. If we look at our base display, it's making me realize that why are we even fetching it all the way at the to do item?

This doesn't make any sense at all. We can actually get rid of this here. We can get rid of this prop item type and we can actually just do it directly inside of here because we already have the information from the route. That's the only time we're using this component at this moment.

So again, this is a specific refactoring that we have data that show that it's being supported and used this way. If it were being used in a more generic way, maybe that wouldn't be necessary. So now to prove that this works, we can now, let's go ahead and come in here and let's do the const route = useRoute and this time let's go ahead and log this again to see what we get.

And so inside of here, if I open that up, there we go. Yeah, I know it's missing a prop type, I know you're yelling at me. So params, object value. Yeah, looks like it's still empty, which is totally fine. Okay, href center of value display to do the same deal, interesting.

Okay, so we have this and then we have the other piece that I'll just go ahead and paste. Not that one, this one, okay, we already learned how to split it up by the item type. And so we have that, rather than that, we can actually now just integrate item type into our URL.

But more importantly it kind of begs the question, why are we even waiting for the user to click on it? Let's just actually call it on when it's mounted to the page, that makes the most sense. So we can call a lifecycle hook using the on whatever the lifecycle hook is called, that's how these composable is work within lifecycle hooks on composition API.

Because if we just didn't mount it before create, you've run into name clashing issues, so the on makes it consistent with like, this is on a specific event, a lifecycle event. So onMounted, what are we going to do? We're gonna run this fetch thing, we are not even I'm gonna click on it anymore.

So now that we have this and we have the item type, we can actually then say, okay, well, I can delete this button, don't need that anymore. Save and I'm gonna delete this item type, because we don't need that anymore. So now, if I refresh, okay, that's looking pretty good, it instantly blinks, instantly shows.

Now, the only thing that we got to do though is, now that we're on the to do viewer, to do the viewer is actually gone at this point, that's gone. Okay, so what we need to do is that if the query says, completed, we really should only show, we should just hide remaining to be totally honest.

And so, for simplicity's sake, we're just gonna hide the remaining count versus the completed count. We're not going to worry about filtering out everything, although you know what, maybe for fun it actually would be nice to do that. So let me actually just show you how that would be done, because anytime we get a chance to demonstrate computer properties, I always like to do so.

So let's do a quick template, v-slot:list. Just like that, and then for now, we can then say, okay, for every li v-for and then we say, todo in todoList. And then key is todo-id just like that and then we can for now just go ahead and let's go ahead and just close that, input type checkbox.

Again, the checked is bound to whether or not todo.completed is true. And then after that, we show the todo.title. Okay, so to make sure this works, let's go back and check, not rendering anything. We have a slot name of, the slot name is items. That's why it's not showing up anywhere cuz I'm sending it to a non-existent location.

Great, okay, so we're gonna switch that, this is the items and now much better.
>> To circle back real quick, is there a reason that you used the mounted lifecycle hook instead of created?
>> No, non regular, we totally use created too, I think mounted is just like a habit of mine.

But let's go and see if created actually works. Before, I was using onMounted and the question was, why not use something like created or before create? You'll see here in the lifecycle hook diagram, there actually is a before create and created. So you are spot on as far as that goes.

But what I always forget is that the setup is the first thing that ever runs. So really actually, as early as humanly possible, it actually is nice to run it then. So I think out of habit, when I just want to be sure everything's mounted to the page and then I like load the thing, but I'm pretty sure if we just fetch it here right inside of our script setup block then we go inside of here.

Let's see, yeah, it's working pretty instantly. So granted, I think to the naked eye it might not be discernible, right, because the onMounted also had like a blink. So we won't talk about performance optimizations but that was a great suggestion, your point to take it away from onMounted cuz that's a couple of steps down the lifecycle that we would have had to wait till it kick this process off.

Okay, so now that we have this, this is great. All right, so I mentioned now that when you're going through this and your todoList, your first instinct might be, especially when we're wanting to check, something along the lines of v-iftodo.completed is true, then show it. But as a rule of thumb, you do not combine your looping mechanism with your conditional rendering mechanism, because you just have a bunch of performance like cluster forks that end up happening.

So the better way of doing this whenever you wanna filter out a list is to actually create a computed property, because you basically have a dependency and you wanna have that do the caching and prevent all the foot guns possible. So what we can do is one actually, you'll see we actually did already create one computer property here, which is the completed items and we also have even remaining items here.

So the question is we can also say, depending on whether or not the query comes back true, so what we can do is we can say, const route equals useRoute. And so then let's just log route.query, I think called it completed. So if we go back now inside of here, we'll see that right now this makes sense.

There is no query for completed. But if we just append this with completed and enter complete 10 equals true, much better. Okay, now it actually has a value being passed to it. So all we need to do now is inside of the navbar that I said, we just need to make sure yeah, it says completed true.

So when we click on that, that'll kick it off. And so now we know basically this variable here will be reactive. So what we could do to be honest is we can say, let's see how else are we using completed items right now? Okay, so we're using it by length, that's how we find, okay.

So what I like to do to be honest, I like to basically create another reactive property called filtertodoList. And the reason I like to create basically a separate property is because this is a derivative of this list. And this can be filtered any number of ways. By completed, you can imagine if someone's searching for something, you might wanna filter by title.

It could be anything, but we can keep it simple for this. Because all we need to say, is if route.query.completed is true then for now, again, there's definitely ways to optimize this code, we are just returned actually you know what, I can just return completed items.value. There you go, cleaner, else return remaining items.value.

No, okay, this is gonna definitely create a bug, but that's totally fine. I'm gonna do this intentionally. So we're gonna take this reactive property and we're gonna drop it in here instead. And now you'll see because completed is true, that's what we get. But then the moment completed is false, well, that's weird.

But then if we take it away completely, then it's not everything. But again, this is kind of a buggy, we're not gonna sit here and flush out the UI, because that's another time. We have a lot of features we wanna get through but this is how you can start detecting those things, you certainly rewrite the logic to be like, if completed is false, then do this, etc.

But I think people here can get the gist of the power of that.

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