تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Grid Pagination Multiple of 120:00

Okay, before we begin with our final foray into infinite scrolling in InertiaJS, I want to show you what I've done to the site. I've created a brand new index called Videos, which also uses our infinite scrolling. So you'll see as I scroll down, it works just as well in this grid view. Our new videos load in as we move until we will eventually reach the end of the list here. Now, one thing to note on this front is there's a little trick you'll want to play when you're using grids. You see how there are two missing items here? Well, if I jump into our editor and into the VideoController, note that we are paginating in tens. Here we go, look, we paginate in tens. And that's exactly what we see in our browser. There are eight here, and then two there for 10. And only when I hit that landmark does it load in the next two. So this is a little bit jarring for the user. My recommendation

browser. There are eight here, and then two there for 10. And only when I hit that landmark does it load in the next two. So this is a little bit jarring for the user. My recommendation when you're using grids with infinite scrolling is to use multiples of 12, because 12 is divisible by 2, 3, 4, 6, and obviously 12, which means that almost any number of items you would naturally have in a row of grids is going to work with infinite scrolling. So now if I reload and I slowly scroll down, we have all of these items here loaded, and then it auto loads the next page for us. So a much more seamless way of working with grids and infinite scrolling. If I jump into the code here, and we take a look at our videos file, note that I am repeating all of this same information, this same code over and over again, the function to load more items, the observer for intersecting, tracking the items

Identify Duplicate Scroll Logic1:45

note that I am repeating all of this same information, this same code over and over again, the function to load more items, the observer for intersecting, tracking the items in a ref, tracking the initial URL. And I'm also having to do this extra bit here, because in this case, we have a filter that allows us to switch the creator of the videos. However, that means that I have to catch this on success handler and reset the items being passed in. So there are a few things we want to think about here. I certainly don't want to have to rewrite all this code every single time I want to implement infinite scrolling. In Vue 3, using the Composition API, we're able to wrap up all of this information inside something called a composable, which allows us to reuse this across as many pieces of our code as we would like. So let's take a quick look through the code again and decide

something called a composable, which allows us to reuse this across as many pieces of our code as we would like. So let's take a quick look through the code again and decide where our composable should come in. We have the items that we're keeping track of. Well, that will be the same across all implementations, as will this initial URL. The function to load more items will be exactly the same. We'll obviously need a way to call this function inside our component, unless we're using an intersection observer. So in my mind, all of this code here, from the items to the initial URL to load more items, could be one composable. Then we have this section with the intersection observer, where obviously we're checking to make sure we're allowed to do something. And then although here we called load more items, we could technically call any function here, right? So in my mind, this is another composable

Create useInfiniteScroll Composable3:25

make sure we're allowed to do something. And then although here we called loadMoreItems, we could technically call any function here, right? So in my mind, this is another composable that we could build. So two composables, intersectionObserver, and obviously our infiniteScrolling pagination part. Let's start with the infiniteScroll. So I place my composables in a directory under js called composables. You can place them wherever. And the convention is that you name your composables, use, followed by the thing you actually want to do. So in our case, useInfiniteScroll. Inside our composable, we'll want to export a function called the same name as our composable file, useInfiniteScroll in this case. Okay, let's jump back into our VideosComponent. And let's go ahead and grab everything that we'll want inside this composable. I'll cut it out. And I'll head back into our composable and simply

jump back into our videos component. And let's go ahead and grab everything that we'll want inside this composable. I'll cut it out. And I'll head back into our composable and simply paste it in. Just to show you how we're going to use the API, let's say const. And I'm just going to use an empty object for now. We'll come back in a moment. But this is object destructuring in JavaScript. And I'm going to make that equal to useInfiniteScroll. Now we're going to have to tell useInfiniteScroll which prop we want to use infinite scroll on. I'm going to pass that through as a string. So let's pass through videos, which is our prop in this case, as a string. Okay, so obviously, we're going to accept that prop name here, we're going to have to now update our logic to use this prop name, instead of relying on props like this. And so what I'm going to do is introduce a little

that prop name here, we're going to have to now update our logic to use this prop name, instead of relying on props like this. And so what I'm going to do is introduce a little function that will allow me to very easily get the value. I'll set that to a closure, which uses the page helper from Inertia, grabs the props, and retrieves the prop name that we've passed in. Using this value function, I'm now able to update all the code to be generic. So here I can say value.data. Here I can say value.nextPageUrl. Here I can say value.nextPageUrl again. And down here I can say value.data. So now rather than talking about a specific property that has been passed down to view, this composable is completely abstract. It doesn't know any specific details. All it does is keeps track of items across time and is able to load more items. Now obviously, this load more items is never called, we need

abstract. It doesn't know any specific details. All it does is keeps track of items across time and is able to load more items. Now obviously, this loadMoreItems is never called, we need some way to allow the user to call it. And in a composable, we do that by returning the items and the functions that we want the user to be able to access. So I'll return that items ref so that they can show it in their view. And I'll also return loadMoreItems as a function. So back in our VideosComponent, I can grab those two things from our composable, the items and the loadMoreItems function. Seen as the names are identical to what we had before, the rest of my code should actually just work. So let's scroll down and hopefully, yep, you can see we are getting infinite scrolling working. Just to show you how reusable this is, let's jump back into our original Comments page and make

down and hopefully, yep, you can see we are getting infinite scrolling working. Just to show you how reusable this is, let's jump back into our original comments page and make use of this same composable. So again, I can say const items, loadMoreItems equals useInfiniteScroll. And we want to this time pass comments as the prop name because that's what's being passed down to view. And now we can get rid of all of this duplicate code. And if we go back to our browser, heading to the comment section and scroll down, sure enough, we have infinite scroll working here too. Okay, so there's something I want to change here. And that's this piece of code. Note that when the user changes the filter, after a successful call, we are resetting the items found here to whatever is found in props.videos.data. We have to do a reset. If we don't do this, our front end actually

Add Reset and CanLoadMore7:27

after a successful call, we are resetting the items found here to whatever is found in props.videos.data. We have to do a reset. If we don't do this, our front end actually never changes. So if I come back to our videos page, and I select loop downing, note that nothing has happened. So that's why we're having to do this reset. But I don't like that in this reset, we are manually changing items. Instead, we can add another function to our composable that will allow us to easily reset without having to do this manual work. So in useInfiniteScroll, I'm going to return another function called reset. And that function is basically going to say items.value equals and we can use our value function, and then call data on it. So now if we go back into our videos component, we can grab the reset function here. And instead of manually doing this work, we simply call reset like so. That

call data on it. So now if we go back into our videos component, we can grab the reset function here. And instead of manually doing this work, we simply call reset like so. That means that this should all work again. As I click Jeffrey, the images change, as I click Luke, the images change. But we don't have to do any manual work inside our component. We simply defer to the reset function that this composable provides for us. There's one other little helper that I think would be nice to expose to the end user. And that's this check here, if not value.nextPageUrl. This check is basically, can I load more items. So let's create a constant called canLoadMoreItems. And we'll set this equal to a computed property. So this will only update as and when it needs to. And obviously this is going to be based on whether the nextPageUrl is not equal to null. Now we can

to a computed property. So this will only update as and when it needs to. And obviously this is going to be based on whether the next page URL is not equal to null. Now we can make use of this inside our component. So in here, I could say if not canLoadMoreItems.value, that simplifies this code. But at the bottom here, I can also export canLoadMoreItems. And if I do that, I can then grab it inside my destructured component here, canLoadMoreItems. And I can use this to do some really cool things. So let's say at the bottom of my grid, let's add a <span> that only shows if not canLoadMoreItems. And we'll say "end of the line buddy," something like that, right? If we jump back into our browser and refresh now, I'm going to scroll all the way to the bottom of our list. And we should see here at the bottom, "end of the line buddy." So this now only shows if you've

Build useIntersect Composable9:55

browser and refresh now, I'm going to scroll all the way to the bottom of our list. And we should see here at the bottom, end of the line buddy. So this now only shows if you've reached the end of the list, if there's nothing more that can be loaded. So that kind of shows the power of building composables, of being able to wrap this functionality up in a very easy to use, reusable piece of code that has full access to view state. Obviously, we now have this IntersectionObserver, which we also want to wrap in a piece of code. Now let's just go over the IntersectionObserver again. This is quite simple. We can see how this would very easily be wrapped up in a composable, but then we have to remember we have this unmounted hook where we're observing a ref. So it seems our composable will need to receive an instance of a ref, which it will then go ahead and observe for us. Let's

have this unmounted hook where we're observing a ref. So it seems our composable will need to receive an instance of a ref, which it will then go ahead and observe for us. Let's create that composable. I'll create a new file and we'll call this useIntersect. Again, we want to export a function called useIntersect in this case, and we'll ask for an instance of the ref that the user is interested in intersecting over. We can copy this code here and I'll cut it out. And we can also copy this code here. You have full access to use things like unmounted inside composables. And in fact, you're encouraged to use these hooks. One thing we'll want to do is make sure we deregister when our component is unmounted. So to do that, I can use the onUnmounted hook. And in there, I'll simply say observer.disconnect. Currently, I have reference to landmark, but I've called this ref. So

So to do that, I can use the onUnmounted hook. And in there, I'll simply say observer.disconnect. Currently, I have reference to landmark, but I've called this ref. So we'll go ahead and change that to be ref.value instead. And I also want to make this callback generic here. So we'll accept a second argument called callback, and I can replace that there callback. It would also be nice to be able to pass in these options so that we can edit them as we see fit. So again, I'll strip that out, and I'll pass in an object called options. And I'll set that equal to an empty object by default so that you don't have to pass it if you don't need to. All right, let's see if this works. Here's my landmark. I'm going to say useIntersect. And I want to pass the landmark in. I also want to pass in a closure. The closure is going to be our load more items.

Combine Composables Together12:20

Here's my landmark. I'm going to say use intersect. And I want to pass the landmark in. I also want to pass in a closure. The closure is going to be our load more items callback from this composable. And then I'll pass in our object with our rootMargin in place. Let's see if that works. Here are our videos. And yeah, you can see the scroll bars are changing. This is working correctly. We now have two composables. One use infiniteScroll, the other use intersect. There's one more thing I'd like to try, and that is combining these two composables, or rather using the use intersect composable inside the use infiniteScroll composable. So I'm going to grab this code here, and I'm going to cut it out. And let's head into our use infiniteScroll composable, where I'm going to say that we can optionally pass a landmark. So by default, it's not, but you can pass.

to cut it out. And let's head into our useInfiniteScroll composable, where I'm going to say that we can optionally pass a landmark. So by default, it's not, but you can pass a landmark. Down here, I'm going to paste the useIntersect code. And I'm going to say, look, if you have a landmark, we want to call loadMoreItems. And I'll pass this default root margin in. Obviously, we only want to do this if you've actually passed a landmark. So I can say if landmark is not equal to null, then use this piece of code or use this composable. That means that if we go back into our VideosComponent, and I'll put landmark above, and in here, I'll pass landmark as the second parameter, we should see everything work as we would expect. And certainly it does. But now we're able to perform all of this in a single, easy to use composable. Obviously, we can now update our comments.

Vue 3 ComposablesRefactoring considerations

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟