Check out a free preview of the full Build a Fullstack App from Scratch (feat Next.js) course:
The "Shuffle and Next Song Controls" Lesson is part of the full, Build a Fullstack App from Scratch (feat Next.js) course featured in this preview video. Here's what you'd learn in this lesson:

Scott walks through syncing the player UI with the music with reference to the native JavaScript Howler instance by attaching a reference to the React Howler component. The controls covered in this segment are next and previous, including when shuffle is active and hitting the last song of the playlist.

Get Unlimited Access Now

Transcript from the "Shuffle and Next Song Controls" Lesson

[00:00:00]
>> Now we need to sync up that music with all the UI that we had previously in the player. We're talking about the seeking, and the playing and the pausing, the duration, all that stuff. So it's gonna be a lot of intricate details that go into this. And by no means this is not the only way to do this, there's probably better ways.

[00:00:17] If you see some better ways, you all know how I am, let me know, I'm human, and we can have a conversation, and we might be able to learn something together today. So with that being said, let's hop in to the player. So a couple things we wanna do is one, we need to grab a reference to the native JavaScript Howler instance.

[00:00:44] And we can do that by attaching a reference to the ReactHowler component. In order to do that we need to make a reference object using the use ref hook inside of React. So that's what we're gonna do, so we're gonna go in React at the top right here where all of our other hooks are.

[00:01:03] And we're gonna make another, I guess you could say hook, but it's gonna be for a reference. And I'm just gonna call this the soundRef, and this is gonna equals useRef. I'm just gonna set the default to null, instead of starting value, the initial value. And then all we got to go do is attach that reference to the ReactHowler using the ref prop.

[00:01:27] So we gof to ReactHowler, we can say ref, and then we can say soundRef. So now we can access the native ReactHowler instance using the soundRef objects. But yeah, let's work on getting everything to sync up, the playing and the stopping, and things like that. In fact, actually, I think the playing and stopping probably already works, if you you click the Play and Pause, because we already have it synced here, so that probably works.

[00:01:54] But yeah, we're gonna hook up the Next buttons, the Previous buttons, all that stuff. So I would say the first one I would wanna tackle would probably be the, let's do the Next buttons, the Previous buttons, and then we'll handle the OnEnd. So when a song ends, it goes to the next song automatically.

[00:02:11] So I say, let's do that, and then we can talk about duration and the seeking, and stuff like that, cuz I think that's a little more difficult. So for the buttons, let's look at the previous button. So for here we're gonna do an onClick, and we need it to basically go back to a previous song based off the list of songs that we had.

[00:02:32] So in order to do that, what we're gonna do is we're gonna make a call back for a couple of things. We're gonna make one for next song, we're gonna make one for previous song. So we're gonna come in here, we're gonna say const, I'm just gonna say prevSong, like so.

[00:02:47] And then I'm gonna say const nextSong like this. And if for the previous song, all we're really gonna do is set the index because that's how we're keeping track of what song is being played. We're gonna say setIndex, and because we need the current index to set the next index we're gonna do a call back in this set call.

[00:03:06] And we're just gonna say, hey, is the current index greater than 0 basically? If it is, then just subtract 1 from it. If it is 0, then go back to the end of the playlist and play the song at the end, so it loops back over. So that way you're always playing that, so we'll say songs.length- 1.

[00:03:32] So this state would be a number, it'll be an index. So we're saying hey, if the index is, cuz 0 is a falsie value, so if this is greater than 0 then subtract 1, that'll give us the previous song. So if it is 0, then we wanna loop back over basically, go back to the end of the playlist.

[00:03:48] And then for the next song, it's gonna be a little more difficult because we have to account for shuffle. I don't think people account for, I've never used a music player that accounted for shuffle on previous. Usually, even if it's shuffle, if you hit back it goes back to the song that just played.

[00:04:04] So we didn't have to account for shuffle, although, I mean, it's your music player, you could also shuffle on previous if you want to. I wouldn't expect that to happen, so we don't account for shuffle on Previous, but on Next if I hit Next and Shuffle is on, I do expect it to shuffle.

[00:04:19] So we can't just increase the index by 1, we actually have to account for that shuffle and figure that out. So what I'm gonna do here is almost the same thing. We're gonna say setIndex, we need to call back because we need the current index to make sure that's good.

[00:04:36] And this is very important because when we get into animating the SeekBar, we're gonna be using animation frames that run whatever speed your monitor is, likely 60 hertz, or 60 times a second. So we do wanna make sure we get the current state, so this callback is very important, and we want to check for if you are in a shuffling state or not.

[00:04:59] So we are keeping track of the shuffle with the state, right? We have that use state up here for shuffle. So we could just check that, and hopefully that'll work, wink, wink. So we'll say, if shuffle and we can say, if shuffle then we need to do some shuffle logic.

[00:05:19] We'll come back to that. And then, else, we'll do something else. So if not a shuffle, then really all we gotta do is just return states. If state equals the last thing in the array, which'll be songs.length- 1, so if it's the last thing in the array, then we wanna reset back to 0.

[00:05:41] So that means if you go Next and you're at the last thing in the playlist, go back to the first thing, so that'll be the zeroth index. If not, then just return that index + 1, so just go up by 1. And then for the shuffle logic, we basically want to do the same thing we're doing now.

[00:06:03] So if you ever learned recursion, you're like, wow, I've never had to use it before. This is the first time in your life you're ever gonna use recursion is shuffling. So what we're gonna do here is we're gonna say next is gonna be, we gotta get a random, shuffling is literally random.

[00:06:19] So we'll just say Math.floor, Math.random, and we want to multiply that times songd.length. So that'll give us a random number between zero and whatever the length of the array is. But if we get back an index that's already the current index, then it'll just play the same song.

[00:06:42] So we have to account for that. So now we have to say, well, if the next index equals the current one, then you need to do this again, call next song again. And then at the end just return next. The TypeScript is complaining because, what is it saying?

[00:07:04] Argument type number, number void is not assignable. Yeah, we can just ignore that TypeScript situation there, we should be good to go. We have our return statement there so it's not a big deal.