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

Create toggle like query0:00

Okay, let's update our short list component so that it actually reflects the database data and not just our demo local states. Let's go in our queries file and we are going to export another fetch call export async function, not createPuppy but toggleLikedStatus. It'll take an id for the puppyId, which is a puppyId. Okay. And here we want to hit the /puppy/{puppyId}/like PATCH endpoint where it'll sleep for one second and toggle the ID one.

slash puppy ID slash like patch endpoint where it'll slip for one second and toggle the ID one inside the like by array. Then it gives us the new updated puppy resource. All right, so let's have a try catch block. And I feel like we can use copilot here as long as we review what's happening. We are getting a response from react backend test slash API slash puppies. Puppy .Id toggle like close enough.

API slash puppies. Puppy. id toggle like close enough. The endpoint is called like the method is not POST but PATCH. And we probably need to add some headers to accept Yes. Application JSON. So if we don't have response, okay, like we did before, we get the data and throw it. Otherwise we destructure the data from the response, which should be a single Puppy.

Wire toggle to UI1:21

Otherwise we destructure the data from the response, which should be a single puppy. And we return that and then we need to catch the error. Yep. We can console.log it and throw it like we did in the other function. So let's try that. We are going to use the toggleLikedStatus function in our toggleLiked component on click. We want an async function. And yes, we're going to set pending to true

We want an async function. And yes, we're going to set pending to true and then try to get our puppyCons up. Updated puppy equals weight, how did we call it? toggleLikedStatus. And we need to pass an id, which is going to be the puppyId. Let's console.log this updatedPuppy and then we can get rid of all of that and set pending to false.

and then we can get rid of all of that and set pending to false. We should probably also handle the error state here, but let's just focus on seeing if we can update the puppy and log the data of the updated puppy. All right. So I will try to toggle frisk it. The first one click doesn't seem like anything change. Let's look at the console and uh, updated puppy frisk. It is liked by user one. What? That's a bit contradictory. Let's see what happens if I refresh the page.

It is liked by User one. What? That's a bit contradictory. Let's see what happens if I refresh the page. Huh? Frisk. It is actually liked, it looks like we successfully have toggled the like status in the database. We just haven't reflected that in the ui. Let's try that a couple more times. I'm going to dislike Chase. Sorry buddy. It still shows as disliked and let's go like Yoko, it should show as unliked.

Diagnose stale UI data2:50

It still shows as disliked and let's go like Yoko, it should show as unliked, but when I refresh the page, Yoko should be liked and chase unliked. So we are clearly updating the data in the database, but our UI seems to be stuck in the early version of the puppies array. And if you think about it, it makes sense in the app, the .tsx file, we are fetching the puppies data and we flowing it down to the puppies list,

the TSX file, we are fetching the puppies data and we flowing it down to the puppies list, the short list, et cetera. The likedBy array for the short list comes from that data. So whenever we mutate the likedStatus, we change the data in the database. Our puppies list, our original list hasn't changed. And it's only when we refresh the page that the page gets the new data with the updated like status for the puppies.

that the page gets the new data with the updated like status for the puppies. In other words, whenever we interface with our puppies and toggle the like status for one, we are now dealing with stale data for our puppies list. And it's only when we refresh the page that we get the new one. So once again, here I have unlike Ross and when the page is refreshed, Ross is going to be unliked. So it's almost like we need to invalidate our puppies list.

and when the page is refreshed, Ross is going to be unliked. So it's almost like we need to invalidate our puppies list whenever we toggle the like status because we have mutated the array of data that we had fetched initially. These sort of challenges make it super tricky to work with a synchronous remote data remote state. Essentially what we've done is taken the state from the database and then try to derive it inside our puppies array. And now when the database changes, our state becomes stale.

database and then try to derive it inside our puppies array. And now when the database changes, our state becomes stale. So again, this is where a framework or a library like React Query is going to be super helpful because it's going to keep track of what mutations have happened and what queries should be invalidated and ref fetched. Alright, I don't wanna keep this video too long, but let's go and implement the short list because currently it is not reflecting

Refactor shortlist state4:38

but let's go and implement the short list because currently it is not reflecting what is liked in the array of puppies. It's just showing the static one and three ideas from the local states. Okay, let's go radical here and remove the local liked status that we had. This is going to break everything, but it's going to tell us where we need to stop relying on passing props down.

but it's going to tell us where we need to stop relying on passing props down. And before I sort the short list, let me go fix up the puppies list. Remember at the bottom we've already stopped passing the liked and set liked to the like toggle, but we now need to stop doing this little dance of passing it down multiple layers. And this might remind you of the work we've done when we did the context API exercise.

And this might remind you of the work we've done when we did the context API exercise. So I am removing the propDrilling of the like and setLiked, which is never used and I can also remove that. So we should be good with the puppiesList and now we can tackle the shortList. So liked and setLiked do not exist anymore, so don't rely on these. And so the first thing we need

so don't rely on these. And so the first thing we need to do is update our logic instead of having a liked array that includes the popId. We need to check here if the pop that's liked by array includes the current User, which is user1. Once again, delete this and go pop that liked by that includes 1 that should take care of the display. But we still have a problem here with the unclick.

that should take care of the display. But we still have a problem here with the unclick. The good news is we've already created the fetch request for this. So we can turn this into an async function and instead of using setLiked, we will await toggleLikeStatus and pass the puppyId. So we have no visual async pending state here, but that should work. So if I add Chase once again, it'll not show up,

but that should work. So if I add Chase once again, it'll not show up, but I believe if I refresh it'll now show up. This is the stale data at play once again. And if I remove Chase now, we won't have any visual cues, but I do think that when I refresh the page, Chase will be gone. So it worked. And so here the fix would be to have a pending state like we've done before. cons pending = pending

to have a pending state like we've done before. Cons pending is pending equals useState set to false. I'll import your state. And then inside this async button click handler, we will set EEND to true, await for the action and then set it to false. That means that we can also improve the UX by disabling the button while it's pending and we can instead of just always showing cross,

the button while it's pending and we can instead of just always showing across, check if it's pending. And if yes, we'll have a lower circle. Should I trust copilot? Yeah, let's try to trust it. I should not have done that because it's not the heart, but it's the X icon we want. If it's not pending, if I delete this, we have a lotus circle, otherwise we have this close button. I think that should cover the pending ui.

we have a lotus circle, otherwise we have this close button. I think that should cover the pending ui. It should be pending state and And okay, I see a few problems here. First one, which is not very important, but let's have a smaller circle icon to match the close button class here. And what you may have noticed, uh, is that all three had the spinning circle while it was happening instead of just one.

that all three had the spinning circle while it was happening instead of just one. And so we could have some extra logic here. I think the simplest technique here is to grab the whole button and make it its own delete button. So function, delete button, and it's going to return all of that, which means we need to move the state here down to the delete button.

to move the state here down to the delete button. Apologies if I go a bit quick, but these are all points that we've looked at before and our delete button also needs the puppyId and I think that's all it needs. So when we pass it here, we are going to pass an ID as well, which we are going to receive here. Not a number come on, but a puppyId total like status using that ID

Not a number come on, but a puppy ID total like status using that ID that is passed to it. And I believe now because the button is isolated, instead of being part of a array iteration here, we should have solved the problems. I wanna refresh the page because I feel like there's only one liked puppy left after my demos. So I will like a few more puppies.

after my demos. So I will like a few more puppies that's like Bella and refresh the page. So now we should have a whole lot of liked puppies. And so now when I remove one, only the one I click should have the spinning icon and in an ideal world disappear. But we're still facing that stale data problem, which means that our UI doesn't refresh. And you know what? Let's try something here.

Return updated puppies list9:25

that our UI doesn't refresh. And you know what? Let's try something here. Let's say you had the ability to change the API endpoint, which is not always a given, but instead of returning just one puppy, what we wanna do is return the same that we do when we get all puppies. And here, whenever we've toggled a like status successfully, we want to return the collection of all puppies, which would be the updated one.

we want to return the collection of all puppies, which would be the updated one. Now in my main component in the short list, I will also pass the ability to set the puppies on the main component. So setPuppies equals setPuppies. In the short list I will receive the setPuppies, setPuppies, which is dispatch setState action with an array of puppies. And so now in the button, in the delete button here.

with an array of puppies. And so now in the button, in the delete button here. Oh, so I need to also pass it here. Set puppies equals set puppies. Now here when I receive the set puppies, state setter, Bear with me. Dispatch. Set state action puppy. Here we go. Now in my unclick handler, I can store the new puppies that accounts new puppies. And this is what I'm expecting coming back from a

I can store the new puppies that accounts new puppies. And this is what I'm expecting coming back from a successful API call. So let's try to console that, log these new puppies and I'm going to delete puppy and hoping that I'm seeing the updated array of puppies. So let's go find puppy here and see if it's liked by user one. And it's not. So calling setState puppies with the new puppies should flush the main component.

And it's not. So calling setState puppies with the new puppies should flush the main component and fix our problem. The cool thing is if that works and I remove chase, it should not, not only remove it from here, but also toggle the heart here because the puppies array is going to be updated here in the puppies list component too. So let's try remove chase and hope for the best. Hey, that worked. Now the other way does not work yet.

Prop-drill setPuppies updates11:31

So let's try remove chase and hope for the best. Hey, that worked. Now the other way does not work yet because we are not setting the puppy state to the new state like we do from here. But let's go and do just that. So in app.tsx, like I do for the short list, I will pass the setPuppies to the PuppiesList. We need to update here the PuppiesList to receive setPuppies. And I will paste that here.

to receive setPuppies. And I will paste that here. Okay. And I just realized I need to drill that down two levels. I am now dreaming of a context API once again setPuppies. Let's do that real quick here. We receive the setPuppies too and we pass it to the likeToggle. Hopefully you're following along at the speed of light. So like I was saying, I am drilling down the setPuppies,

Hopefully you're following along at the speed of light. So like I was saying, I am drilling down the setPuppies, stateSetter so that whenever we do an update here, we can receive the new puppies array from that toggle like status that we've updated. And then Copilot should know and it does, we can set puppies to the new puppies. And so I apologize, I know this was a lot, but essentially we now have a mechanism

And so I apologize, I know this was a lot, but essentially we now have a mechanism that gives us the updated fresh data from the database, from the API whenever we do a toggle action for the like status. And so we can flush our application with the new state being comfortable and confident that this is reflecting the latest state on the database because this is the database and the API that gave us this data.

the database because this is the database and the API that gave us this data. So now I like the chances that the data in my app is going to stay up to date. So if I like frisket, I'm expecting it to go pink and be added up here. If I remove Rex. The same with Rex. Where is Rex? Oh, down there. We missed it, but let's toggle it back on and it'll go pink and it's going to be up here. And just to make sure we are fully understood that it works,

and it'll go pink and it's going to be up here. And just to make sure we are fully understood that it works, I'm going to add Luna and Puppy. They both get pink and they both get added up here. So we did find a way to keep our data fresh and in sync with the database, but this has two flows. The first one is we had to modify the API for it to work and accommodate our needs. And the other one is we ref fetching the whole data every single time.

And the other one is we ref fetching the whole data every single time. We don't have any caching happening and this is probably a bit expensive and over the top. In the next lesson, we'll tackle the new puppy form to complete our refactoring.

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