Passing Liked State0:00
Welcome back. Did you manage to get the short list going if you did, great job. If not, that's fine. We are going to go through it together. All right, so we want to display one puppy here for each of the shortlisted puppy. In our main component, we have disliked states that we've passed down to the puppiesList and all the way down to the likedToggle. And we are going to do the same pass the
and all the way down to the liked toggle. And we are going to do the same pass the states to the short list. So liked, setLiked, and setLiked. We're getting prematurely yelled at by TypeScript but we are going to go and receive those here. liked, set, liked and define a type that takes liked as an array of puppy IDs.
and define a type that takes liked as an array of puppy IDs. Remember? And the setLiked is going to be a dispatch setState action for an array of puppy IDs. And remember that type comes from react and it's been imported up here as I used it. All right, so why don't we start by just outputting the data just to make sure that we can actually access it. Pret tag json dos string liked
that we can actually access it. Pret tag Jason dos string I liked and here's our short list. But this time instead of just having a static one three default value, we should be able to see that update whenever we toggle a like status on any of the puppies. Super cool. So everything is working as we expecting. We sharing the states between the puppies and the short list through the whole main app.
Rendering Shortlist Items1:30
We sharing the states between the puppies and the short list through the whole main app. Alright, so I can remove this. That was the first part of the challenge is to pass the state down. And then we have this ano list of static markup, repetitive list items like we had for the puppies list. And so at this point we want to output one li item for each puppy that is in the liked array. Not all the puppies, only the ones that are liked
for each puppy that is in the liked array. Not all the puppies, only the ones that are liked but we are missing some crucial information here, like is just an array of puppy IDs. So we technically not getting any puppy data inside this component. Just an array of numbers. So we need to also receive the puppies here and I can type it here. puppies is an array of the puppy type.
and I can type it here. puppies is an array of the puppy type and so we're now being told that we also need to pass the puppies, which is what we are going to do. puppies equals puppies. So we are passing the same puppies to the shortList that we pass to the puppiesList. And remember at this point this is static data coming from this file up here. Okay, let's go back in our shortList
this file up here. Okay, let's go back in our short list and we are going to handle our dynamic list in two steps. First we're going to output all the puppies, puppies.map and for each puppy we are going to render one of the LI items. Now remember we need to pass a key here, key equals puppy.id and I'll go and delete the other item which we don't want anymore. And so that should output a shortlist card.
we don't want anymore. And so that should output a shortlist card for every single puppy in our puppies array. And yet we do and all the love goes to chase since its static markup. Cool, so let's update the data in our li item. So I'll expand this and so we have the alt tag with the puppy that name the image source with puppy.image_path. The name is here again puppy.name.
that name the image source with puppy.image path. The name is here again puppy.do name. And I think that's it for the data but we are now having another SVG icon. You can see this one is called LucidX. These two classes are output by the Lucid React library when you copy and paste components. And so these tell me that the components in the Lucid React library is called X.
And so these tell me that the components in the Lucid React library is called X. And so up here I can look for X from Lucid React and I will pass a class name to match what we have done here and check this copilot knows exactly what we want, which is this set of classes minus the lucid ones. So I'll press tab. I will keep this SVG just now to compare both and we should have two identical close crosses. Perfect. And you can see the name
identical close crosses. Perfect. And you can see the name and pictures are now showing the relevant puppy. Very cool. So I can collapse and delete the whole SVG icon. And this is our step one sort of done displaying one ally item for each puppy and it all looks super nice. Alright, but now I wanna show only Frisket, Leah and let's say Yoko. And so Chase, sorry this time you're not liked.
Filtering by Liked4:21
and let's say Yoko. And so Chase, sorry this time you're not liked. We wanna only show the puppies that are liked in this short list and that's actually super easy to do here. We mapping through the puppies, but before we map through them we need to filter out the puppies that are not liked. So I can chain this into a chain of array methods and before the dot map I will go dot filter.
So I can chain this into a chain of array methods and before the dot map I will go dot filter. And remember this time a pop is one index of the puppies array. So it's an entire puppy here what I wanna do is only keep the puppies that are included in the liked array. So I'm going to filter for the condition where the puppy id is included in the liked array. So we're going to take the liked array
where the puppy id is included in the liked array. So we're going to take the liked array and then check if it includes the pop id. So essentially we take all the puppies, we run them through this filter that only keeps the one that are included and then we map over what's left. So we have this nice multi-step chain of array methods here. And I think with that in place we should have a fully dynamic and working short list. So when I un tole frisket away it goes.
dynamic and working short list. So when I un tole frisket away it goes. If I ret toggle her back, she comes, let's add Chase one more time. Remove Chase and who didn't get much love, Ross definitely didn't get enough attention. He's very cute. So now we have Frisket, Leah, Ross and Yoko added to our short list. If you manage to get to this point by yourself, well done if you took it even one step further
Removing from Shortlist5:43
If you manage to get to this point by yourself, well done if you took it even one step further and implemented the remove from short list functionality that we are about to look at. Hats off to you. Alright, so as I just hinted to, we can toggle on and off a puppy in the short list from the puppy card but deleting or trying to delete and remove a dog from the short list is not working because we haven't implemented that yet.
and remove a dog from the short list is not working because we haven't implemented that yet. The place this is going to happen inside our PuppyListItem is this button here we want to add an onclick event listener like we did for the likeToggle component. And that's again inline the function. And if we've done things right, if we at all see this button to click because we are in the short list, it means that the item is in the short list.
to click because we are in the short list, it means that the item is in the short list and so we want to remove it from the list. So I don't even need a multi-line. All I need to do really is call the setLikedState setter that we have received in our component here. And we know that we want to remove the item from the liked array. So remember we can filter it out by doing liked.filter and just like copilot suggests we going to receive the id
So remember we can filter it out by doing liked that filter and just like copilot suggests we going to receive the ID and then keep all the puppies except the one that matches the ID since that's the one we want to remove. So we check for is not equal to and we keep all of these essentially removing the one that is equal to it. Alright, let's try that. Say goodbye to frisk it gone Leah, Ross and Yoko, it works.
Say goodbye to frisk it gone Leah, Ross and Yoko, it works and I dunno if you were paying attention to the hearts down here, but as I was removing the dogs from the short list, the hearts he went back to unlike. So everything works. Look at Leah down here. Go Chase, go and Fris get co and hopefully things are starting to click together in your head at this point.
Visualizing Re-renders7:29
and hopefully things are starting to click together in your head at this point. And you can see the power of this beautifully simple mental model in React. It's a beautiful cycle of state, props, and re-renders. You have states defined at a specific level depending on where it needs to be accessed and then you have props to pass it down to the components that need that state. From there the setState action is called
to the components that need that state. From there the setState action is called and trigger a state change alerts React that something change and React re-renders the components that need to. I think right now is the perfect time to bring a neat little browser tool that's going to help us visualize this re-render cycles. This tool is called React Scan and it's awesome. I could explain you what React Scan does
This tool is called React Scan and it's awesome. I could explain you what React Scan does but instead I'll straight up show you I will copy the <script> tag here and you just get a hint of this tool. And in my v-apps/index.html, the entry point I will paste the <script> tag. Uh, we don't have any <script> tags here so I will paste here before the closing </document> <head>. That's all I need to do. And if we look at our app once again,
That's all I need to do. And if we look at our app once again, we have now this little toolbar here. One of the key things React scan does for us is an eye-opener. It's going to show us every time a component re-renders whenever we interact with the UI. So if I go in here and type some search, you cannot see anything in terms of extra UI but if I go down
you cannot see anything in terms of extra ui but if I go down and toggle a like whoa, have you seen what happened? Every component that had to re-render kind of flashed in purple with the component name, toggle, toggle. And your first reaction here should be like, well everything re rendered, well not quite. Let me scroll back up so we can see more of the UI and I will toggle the heart.
Let me scroll back up so we can see more of the UI and I will toggle the heart. Once again, as you can see, these components here have not re-rendered. If I remove something from the shortList, again all of these components here re-render but the top one doesn't. So what's happening here? Well the common denominator between all these components that had to re-render is the fact that the state for the liked array has changed.
that had to re-render is the fact that the state for the liked array has changed. Now remember in our app's entry point we have this main component here and this is where the state is defined. So essentially these components here are not re-rendering but main because the like state has changed is re-rendering. And something you need to understand is whenever a component re-renders all of its children components will also re-render even if they don't have any state or any data that changed.
of its children component will also re-render even if they don't have any state or any data that change, if a component re renders all of its children will re-render. Now this is not entirely true because there's a way to avoid this from happening using things like React.memo, but that's the default behavior. If a component has to re-render, it'll re-render all its children.
If a component has to re-render, it'll re-render all its children. So that might sound scary and inefficient at first, but re renders are extremely fast and you can go a long way before this becomes a bottleneck. Matter of fact, you can see these 60 frame per second information here and basically React scan is also going to listen. You can even have an audio alert for things that are going to slow down the frame rates.
You can even have an audio alert for things that are going to slow down the frame rates. And so if I scroll down and frantically click on the like heart like, like like, like like, like like, like like, like like like you can see, can see not a single phone has been dropped, even if everything was re rendering. React can also has this inspect tool that's going to allow us to zoom in into any component that we've extracted and so we can see what happens.
to allow us to zoom in into any component that we've extracted and so we can see what happens. So let's try to click on Lia and we can see the data that this component has. So all the data for Lia, you can see the liked array and any other props it has like the setLike function and if I continue toggling the liked array like so a few times you can see we have this really nice what has changed uh, dropdown and it shows us what has changed.
what has changed uh, dropdown and it shows us what has changed. So this Onfi might look scary but basically it shows that the first index in the liked array, which used to be number three, so there's an array of two and three then became undefined and then became three again. And you can see the re-render history and scrub through the state changes like this to really understand what's happening.
and scrub through the state changes like this to really understand what's happening. This tool is super great and as your React application grows, it's going to help you make informed decisions on how to improve the performance. If you notice some frame drops or some expensive component that keeps re rendering and there's a way to avoid this, you'll be able to make decisions by just having a look at React
State Placement Impacts11:34
and there's a way to avoid this, you'll be able to make decisions by just having a look at React scan and just to drive home. The point of the scope of componentry renders like you can see up here doesn't render. I'm going to take this like state out of my MainApp and I'll move it all the way inside the MainApp components and then I will pass it here to the MainComponent. As we've done so many times,
and then I will pass it here to the main component. As we've done so many times, we won't worry about the types here since I'll delete that, but I'll receive liked and setLiked here so everything remains the same but the like state is defined at the root app component and then pass to main and this time watch what happens when I remove an element from the short list, boom, the entire app including the page wrapper component,
from the short list, boom, the entire app including the PageWrapper component, everything re-renders. And so imagine that inside my PageWrapper completely unrelated to the PU stuff, I had an expensive calculation component here that was doing some crazy compute intensive calculations. Well every time we would just like a puppy, the whole calculation would re-run up there for no reason, that knowledge should inform you on a very important point.
the whole calculation with rerun up there for no reason, that knowledge should inform you on a very important point as much as you can, don't bring state higher up the render tree that it needs to find the place that it needs to be to share with other components. But don't just put it right at the top at the root to make things simple for you. That said, for a simple app like this one, it wouldn't really matter anyway. And this is why React Scan is such a great tool
it wouldn't really matter anyway. And this is why React Scan is such a great tool because it's going to tell you when you actually should worry about something you're doing wrong and there's reasons and benefits to making a modification to your code to reduce some re renders. That can be a bit expensive. Alright, let me undo these fake components, remove the props pass and we are going to bring this back to the main components
remove the props pass and we are going to bring this back to the main components that doesn't need to receive these. So we back to what we had, I'm going to comment out, react can for now and we can come back and toggle it on and off as we need. And let's appreciate one more time, how cool our short list and liked puppies functionality works super great. I can add puppies, they appear PI can remove them and this is all synced.
I can add puppies, they appear PI can remove them and this is all synced with the shared state that we've created. Good stuff. We should tackle this search and filtering functionality next. But since we are on the topic of state, props, and res, I wanna quickly show you a technique that is super useful when you want to pass props directly to deep nested components.
to deep nested components.
