We often need to move in one direction or another in a JavaScript array to focus on one value at a time. When we hit an upper or lower bound, it's convenient to have the referenced index jump to the other end of the array so we can keep cycling through in that same direction. In this lesson, we'll apply this to a React UI, allowing the UI to "jump" to the beginning of the array when we hit "next" at the end of the array, and to jump to the last item in the array when moving "back" and we hit the lower bound of the array and we'll do it by taking advantage of the %
(modulus) operator.
Instructor: [0:00] We can flip our card between front and back, but we still can't progress through our cards with the next and previous buttons. Let's wire these up, starting with the next button.
[0:10] In my class component, I'm going to create a new property on the class. I'm going to call it handleNextCard. This will equal an arrow function. Inside the arrow function, I'm going to call this.setState. I'm going to take the existing state value.
[0:26] I'm going to return a new index based on that. I'll wrap this in parens and then create an object literal. I'm going to return a new value for currentIndex. I'm going to set that to state.currentIndex plus one.
[0:45] Now that we have this defined, let's wire it up to our button. I'm going to scroll down to my render method. I'm going to find my next button. I'm going to give this an onClick. That'll be reference to this.handleNextCard. I'm going to save that. Then we'll go back in the browser.
[1:05] Now when we click on the next button, we'll see that it progresses through our cards. We're on the last card. If I click next again, it's going to blow up. We're going to get an error that it can't read property term of undefined. The problem is our index has gone beyond the length of the array. Let's go fix that.
[1:22] Let's go back to our handleNextCard function. We need to figure out how we're going to handle incrementing this index and also sending it back to zero when it hits the end. We could add a bunch of logic in here to look at the current value against the length of the array, but there's a better way.
[1:40] Let's pull up some sample code here real quick. I have a stand-in for our array length. If our length is three, our valid index values are zero, one, and two. We'll start with our current index of zero. Then we need to figure out what the next index is going to be.
[1:55] I'm going to start with what we currently have, which is taking the current index and adding one to it. That'll give us a next index of one. We'll see down here if we're starting at zero. That's what we want. Then if we go to one, our next index value will go to two. Two will take us to three. Three here is not a valid value.
[2:19] What we can do is we can take this. We can group this together, so currentIndex plus one. Then we're going to use the mod operator. We're going to put length after that. You'll see here that with a current index of two, this sends our next index back to zero.
[2:37] It's going to take the length, which is three, and try to divide it into whatever value is calculated in these parens. Length is three. Two plus one is three, so this is going to return a zero for any of the values that are underneath our length.
[2:53] When we have one incremented, our value is two. Length won't divide into that at all. It'll just give us back this value. We can effectively increment and have it cycled back to zero just using the mod operator. Let's apply this to our component.
[3:11] We're going to come back over here. We're going to do the same thing. We'll take this state.currentIndex + 1. We'll wrap it in parens. Then we're going to throw mod. Then we went our cards.length.
[3:24] Right before this call to setState, I'm going to destructure this.props just to get cards. Down here, we can just say cards.length. We'll save this. Let's go back to our browser. We can try our next button. We'll click. Then we'll come back around to the beginning.
[3:48] This will let us basically click next forever. It'll just cycle through all the different index values available in our array. Since this is dynamic based on that length, as we add more cards to the deck the functionality will remain.
[4:03] Now let's implement the handler for the previous card. I'm going to drop down. I'm going to add a new property to my class. I'll call handlePrevCard. This will equal an arrow function. Inside the arrow function, I want a reference to cards because we're going to need the length of that again. I'll just do that up front. That'll be destructuring this.props.
[4:24] Then I'm going to have a call to this.setState. We're going to use our existing state to determine our new state. We'll return this object literal. Again, we're changing the currentIndex. I know I want to update currentIndex and give it a new value based on state.currentIndex.
[4:47] We're going to want to subtract one, but this is going to be a problem when we get back to zero. We're going to use the mod operator again. This time, we're going to take this value, put it in parens. We're going to add cards.length to it. Then we're going to use mod cards.length.
[5:07] Before we run this in our UI, let's look at a quick example to see how this code works. We'll switch back to our small example. I'm going to take this previous one and comment it out. I'm going to define a new next index here. This will be our new calculation. This is going to take currentIndex - 1 + length. We can wrap all of this up in parens mod length.
[5:36] Let's start at the end of our array and work our way back. I'm going to start with a current index value of two. This is the last element in our array. We're going to take two, subtract one from it and get one.
[5:46] We're going to add our length, which is three. We're going to get four and then mod three. Three will go into that four one time. We'll have a remainder of one. We'll essentially get back the value that's in the parens using mod here.
[6:01] Then we go from two down to one. We end up with zero plus the length. We get three. Three mod three gives us zero. We get back, again, that value that's in the parens. Now if we drop down to zero, we're going to end up with negative one.
[6:15] Then we're going to add our length of three, which is going to give us two. Then two mod three. Three won't go into the two, so we'll get the two back. It's going to send us right back to the last item in our array. Let's test that out. The zero brings us back to two. Now we can cycle moving backwards through our array.
[6:35] Let's go back to our component. Let's wire this handler up to our button. I'm going to take this handlePrevCard. I'm going to go down into my render method and find this button. This button previous here, we're going to give it an onClick. In that onClick, we'll reference this.handlePrevCard. I'll save this. Let's go back to the browser and test it out.
[6:59] When this loads up, I'm on my first card. I should immediately be able to hit previous and go back to the last card in our deck. We'll see that it works. I can cycle backwards and forwards without ever running into a point where it has to stop or I get an error.
Member comments are a way for members to communicate, interact, and ask questions about a lesson.
The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io
Be on-Topic
Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.
Avoid meta-discussion
Code Problems?
Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context
Details and Context
Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!