Jammming Project => Step 49

While doing The Jammming Project’s Step 49, I couldn’t wrap my head around the way the solution works. Even by watching the walkthrough, the code used in there is just a blur.

This code is responsible for a process that removes a song from a user’s custom playlist when the user selects the - sign, inside of a rendered track:

removeTrack(track) {

    let tracks = this.state.playlistTracks;

    tracks = tracks.filter(currentTrack => currentTrack.id !== track.id);

    this.setState({playlistTracks: tracks});

  }

What I don’t understand is the function of this part:
tracks.filter(currentTrack => currentTrack.id !== track.id)

I’d really appreciate it if someone would explain it clearly.

Hi Nima,
let’s go through line by line:

Here you temporarily save the tracks saved in state to the variable ‘tracks’ in order to be able to alter the list without having to use the state setter.
tracks is an array of objects. Each track is an object with an id. ‘tracks’ looks something like this:

[
{id: 1,
name: 'Numbers',
artist: 'Booka Shade'},
{id: 2,
name: 'Breathe',
artist: 'The Prodigy'},
]

Now you call the function removeTrack(track) in the Track Component, passing a track to it:

removeTrack({id: 2,
name: 'Breathe',
artist: 'The Prodigy'});

That is now passed to the filter method and the returned array is reassigned to the ‘tracks’ variable:

Iteration 1:

tracks.filter({id: 1,
name: 'Numbers',
artist: 'Booka Shade'} => 1 !== 2); // this is true: 'Numbers' is returned and saved to the 'tracks' variable.

Iteration 2:

tracks.filter({id: 2,
name: 'Breathe',
artist: 'The Prodigy'} => 2 !== 2); // this is false: 'Breathe' is not returned and not saved to the 'tracks' variable.

Now the remaining object is saved to the state with the state setter:

1 Like

Thank you for your comprehensive answer.
Helped me a lot in understanding it, but there’s still one thing:

When ‘Numbers’ is saved into tracks, what exactly will happen?
I mean how is this function gonna remove that track with the help of this function declared in another component:

    removeTrack() {
        this.props.onRemove(this.props.track);
    }

I’m sorry if my question is a little vague for I myself don’t exactly know how to put it in words.

So I understand that you understood the way the function itself is working, but you don’t understand how it can be called in another component, right?
The tracks are saved in the state of App.js.
You pass the tracks and the function as props all the way down to the Track component. I don’t remember how many components you’re passing it through. This way you’re making the function available to the child component. In App.js you render the Playlist component:

<Playlist 
              onRemove={this.removeTrack}
              playlistTracks={this.state.playlistTracks}

Now the tracklist and the function is available in the Playlist component. And this way you pass it to the Tracklist component and so on…

You can review the chapter about passing props here:
https://www.codecademy.com/paths/front-end-engineer-career-path/tracks/fecp-react-part-ii/modules/fecp-components-and-props/lessons/this-props/exercises/receive-event-handler-prop

1 Like

Thanks again for your asnwer.
No, I get how the components work but that particular function itself is confusing me.

In your example our track has an id of 2 and that gets compared to the objects which are in let tracks = this.state.playlistTracks

If their ids differ then we store the current track in tracks ( this.state.playlistTracks ), if their ids are the same then we don’t save them to tracks.

My final question is this:

How is this process helping us and enabling us to remove the current track that we clicked on?

Have a look at what the filter method does:
You apply the filter method to an array of elements: tracks.filter.
The filter method accepts a callback function with a test function that returns either true or false. If the test returns true, the filter method returns the specific item that passed the test:

let tracks = this.state.playlistTracks; // an array containing two tracks
tracks = tracks.filter(currentTrack ...

currentTrack is ‘Numbers’ in the 1st iteration and ‘Breathe’ in the 2nd iteration.

=> currentTrack.id ...

currentTrack.id is 1 in the first iteration and 2 in the second iteration.

currentTrack.id !== track.id

track.id is 2 because the id of the track object passed as an argument to the removeTrack function is 2.

2 !== 2

is false. So the track isn’t returned by the filter method because the test failed.

tracks = tracks.filter

tracks is reassigned. The filter returns only one item: ‘Numbers’. So tracks looks like this now:

[
{id: 1,
name: 'Numbers',
artist: 'Booka Shade'}
]

And now this array of one object is set to state:

this.setState({playlistTracks: tracks});
1 Like

After going through this project’s step 9 and its walk-through, I think I kinda understand how that function works since the remove function in these two projects are kinda similar.

From what I gathered, that function goes through the arrays looking for ids and only returns those items that their ids don’t match the id of the item we’re removing. In this way we’re left with the remaining items in our new array while the item we removed no longer exists in this new array.