Complete Intro to React v4 Adding Carousel Interactivity
This course has been updated! We now recommend you take the Complete Intro to React, v8 course.
Transcript from the "Adding Carousel Interactivity" Lesson
>> Brian Holt: So the next thing we want to do is we want to add the ability to add, so I can click on it that it will show me a different primary image, right? So the way I'm gonna do this is I'm gonna add a click handler and say handleIndex Click.
>> Brian Holt: So typically this would be a method that looks like this. This.setState.
>> Brian Holt: And this is we're gonna take in an event, right? This looks just like a normal event handler that you would see on every jQuery application, right? This event technically is a react synthetic event, right.
[00:00:49] But you can treat it just like a normal dom event. They modeled the API to be exactly the same. And then I would say active and event.Target
>> Brian Holt: And I don't think I did that part yet so we still have to go do that but we'll do it here in just a second.
[00:01:14] We're gonna say, .dataset.index.
>> Brian Holt: Okay? So now we need to go put this data set thing on the image itself so that we know when we click it, that we're getting the index back so that we can set that as the new active thing. So the way we're going to do that is we're going to go to our image here and just anywhere put data dash index equals index, like that.
>> Brian Holt: Yeah, question.
>> off screen male: Are you using state instead of props just to avoid the filter on each rerender?
>> Brian Holt: Yes. So that's a good question. Why don't we just do this, cuz we do it somewhere else. I think we do it in every single render method, we just do the filter.
[00:02:12] [COUGH] The fact of the matter is this can be done once, and then not have to be worried about in the future. And then as props change in the future we can keep re-doing it. But this is not changing very frequently. Nor is the state here changing very frequently.
[00:02:25] So that's why were going to get this derived states from prompts. And in general if you have derived data from prompts this is a really really good way of doing it. Very compelling way. But yeah that is a very good question. We could just move this entire thing to our [INAUDIBLE] to be honest with you, in this particular case, wouldn't suffer much performance hit.
[00:02:53] But I think this makes it simpler. I prefer things that make my render method as simple as possible. Cuz the render method ends up being the most complicated thing every single time. So here, this ends up being a lot simpler because I don't have to worry about filtering stuff out of my data.
[00:03:07] I get to move all of that out into this. And the other cool thing about this, now this particular thing is testable, right? This is very easy to test. I would just import this into my test and then I could test carousel dot and get derive data from props, pass in some fake props and make sure it's giving me the state that I anticipate so I also find that very compelling.
>> Brian Holt: Okay, this is still broken, by the way. So we still have two things that we have to fix on this.
>> Brian Holt: One, we're reading stuff back in from the dom, right, so event.target.dataset ,in case you don't know, this is just a normal dom thing, right? If I put data dash whatever, that's going to be on the data set for a dom object, right?
[00:03:57] Regardless if you're in react or not, right? If I'm in just writing normal jquery, dataset is still a thing there because I have data-index that means I can access dataset.index. Does that make sense?
>> Brian Holt: So that's the first thing, but the problem here is we have a type mismatch.
[00:04:38] So this is not going to be true, that's a problem, right? So we need to cast this to be a number or convert it or coerce it in to being a number. There's a bunch of ways to do this. My favorite way of doing it is just putting a plus sign.
>> Brian Holt: This takes a string and makes it a number.
>> off screen female: Is that coercing it?
>> Brian Holt: Mm-hm.
>> off screen female: Okay.
>> Brian Holt: Yeah, that's actually, there's a bunch of ways to do it, I find this to be the easiest one.
[00:05:23] I don't think I really understand coercion in its greatest depths. The only person that I think that understands it is Kyle Simpson because that guy studies everything. So if you want to know, read Kyle's book or watch his courses on Front End Masters.
>> Brian Holt: But I promise you this works, [LAUGH] this turns a string into a number, okay?
[00:05:47] Next thing, we still have another problem here.
>> Brian Holt: That problem is that we're calling handleIndexClick. We have to put that on onClick handler too, so let's do that. Under image, we have to put onClick, equals, this.handleIndexClick, like that. I'm gonna get,
>> Brian Holt: Yeah, it's gonna be upset about that.
>> Brian Holt: So typically I would tell you to not do this, but for the sake of one, you should always listen to the JSX [INAUDIBLE] stuff and just do what it tells you, images are not interactive elements right, we should make these buttons technically. But for now, I'm just going to show you how to disable a line.
[00:06:35] Eslint-disable-next-line. And this is going to tell eslint, I know I have a problem here, just ignore it for now.
>> Brian Holt: This is dangerous showing you these things because now you're going to litter your code bases with them.
>> Brian Holt: But this should be refactored to be a button and an image inside of a button, right, and then now you can tap through it.
[00:07:09] But for now we'll just make this an onClick handler.
>> Brian Holt: Okay still one more problem here, handleIndexClick. This is an event listener, right? Or events handler.
>> Brian Holt: So whenever I click on this image it's going to call handleIndexClick, right? It's gonna call this.setState. What is this here in this particular case?
>> Brian Holt: It's gonna be called as an event handler, right? But you don't actually really know what context it's gonna be in when it's called. And let me tell you, that is the incorrect context, right? Because you're ripping out this handleIndexClick and you're going to be calling it from the Window, right?
[00:07:56] So it's gonna be undefined or it's gonna be Window. Any either case, it's not the one that we anticipate it being. There's two ways to handle this. We already have a thing called the class properties, right? We already did that, so I'll show you that one in just a second.
[00:08:14] But if you're not using class properties, it would have to be like this. We'd have to go into our constructor so you don't have to type this, I'll just show you this. And then first thing I would say is, super(props) and then I would say, this.handleIndexClick = this.handleIndexClick.bind(this).
[00:08:39] So inside of your constructor, for anything that's going to be an event listener and you calling this dot set state or this dot whatever, you would have to do this. Then, as you pull out this method and then hand it to react a call later. It would be the correct this, right?
>> Brian Holt: And it's going to make sure that whenever you call this method, this is always going to be set to whatever instance of the Carousel that you're doing, right?
[00:09:16] So that's what the bind(this) here does. Make sense?
>> Brian Holt: If you have a bunch of event listeners, this list gets quite long and it gets quite annoying, right. And it's just kind of burdensome to have to do this in my opinion. That's why I'm a huge fan of these class properties, cuz how I can actually fix that now is I can make this an arrow function like this.
>> Brian Holt: Now this works, why? Because function and arrow functions have slightly different semantics when it comes to binding this. When you create an arrow function, it doesn't create a new context when it's called, which means it just reverts to whatever lexical scope it's in, right? If I have a function, so if I have a normal function like this, it creates a new scope whenever it's called, right, wherever it's called from.
[00:10:15] So that scope can change depending on where you call x in this particular case. However if I have const y equals arrow function.
>> Brian Holt: This one does not create a new scope wherever it is, so it just reversed to whatever lexical scope, or wherever it is, right. So in this particular case handleIndexClick doesn't create a new scope, so it just reversed to wherever it's created, which is here in carousel.
[00:11:10] I'm not bitter or upset or anything.
>> Brian Holt: Cool. Is that makes sense why this works now? Hopefully.
>> Brian Holt: There are just really ridiculous conversations that people have about, is this more performant versus one way or the other. You're creating too many instances of, blah, blah, blah, it doesn't matter.
[00:11:34] You almost never hit the performance hit because this is such a small thing. So I would say this is fine, don't worry about it. If people on Twitter at your job say like, well this is less performance like, it's so miniscule, it's such a, you know, atom in the bucket that you will never notice the performance profile here.
[00:11:53] Unless you're writing like really highly, highly, highly performance sensitive things.
>> Brian Holt: So,
>> Brian Holt: Okay, so now if we go back over here, just save, this should start working, and it does.
>> Brian Holt: That is a cute dog.
>> Brian Holt: But, it's pretty cool, right? It changes which one's highlighted because of the active thing, right?
[00:12:27] And, it's actually changing our hero image, as well.