Jamming Project - Step 47 => Uncaught TypeError: this.props.tracks.map is not a function

Hi guys

I’m stumped on the Jamming Project step 47 and was wondering if someone could help?

After completing step 47 and clicking on the ‘+’ button in the dev build I’m getting the white screen of death and the following error in the console:

Uncaught TypeError: this.props.tracks.map is not a function

After searching the Codecademy forums to see if anyone has similar issues, I’ve found a few solutions that have worked for other members but unfortunately, I’m not having much luck with them.

Reading through comments and trying to debug the issue myself I think the error is happening due to the props of my <Playlist /> & <TrackList /> components, but I can’t seem to work out where I’ve gone wrong.

Even watching the walkthrough video I can’t seem to figure it out! :unamused:

Any help would be much appreciated. I’ve pasted my code below but can post a link to my git repository if that is easier.

Thanks!!!



App.js

// import logo from './logo.svg';
import React from "react";
import Playlist from "../Playlist/Playlist";
import SearchBar from "../SearchBar/SearchBar";
import SearchResults from "../SearchResults/SearchResults";
import "./App.css";

class App extends React.Component {
	constructor(props) {
		super(props);

		this.state = {
			searchResults: [
				{ name: "name1", artist: "artist1", album: "album1", id: 1 },
				{ name: "name2", artist: "artist2", album: "album2", id: 2 },
				{ name: "name3", artist: "artist3", album: "album3", id: 3 },
			],
			playlistName: "Awesome Mix Vol 1",
			playlistTracks: [
				{
					name: "playlistName1",
					artist: "playlistArtist1",
					album: "playlistAlbum1",
					id: 4,
				},
				{
					name: "playlistName2",
					artist: "playlistArtist2",
					album: "playlistAlbum2",
					id: 5,
				},
				{
					name: "playlistName3",
					artist: "playlistArtist3",
					album: "playlistAlbum3",
					id: 6,
				},
			],
		};

		this.addTrack = this.addTrack.bind(this);
	}

	addTrack(track) {
		if (this.state.playlistTracks.includes(track.id)) {
			return;
		} else {
			const playlistUpdate = this.state.playlistTracks.push(track);
			this.setState({ playlistTracks: playlistUpdate });
		}
	}

	render() {
		return (
			<div>
				<h1>
					Ja<span className="highlight">mmm</span>ing
				</h1>
				<div className="App">
					<SearchBar />
					<div className="App-playlist">
						<SearchResults
							searchResults={this.state.searchResults}
							onAdd={this.addTrack}
						/>

						<Playlist
							playlistName={this.state.playlistName}
							playlistTracks={this.state.playlistTracks}
						/>
					</div>
				</div>
			</div>
		);
	}
}

export default App;


Playlist.js

import React from "react";
import "./Playlist.css";
import TrackList from "../TrackList/TrackList";

class Playlist extends React.Component {
	render() {
		return (
			<div className="Playlist">
				<input defaultValue={"New Playlist"} />
				<TrackList tracks={this.props.playlistTracks} />
				<button className="Playlist-save">SAVE TO SPOTIFY</button>
			</div>
		);
	}
}

export default Playlist;


SearchBar.js

import React from "react";
import "./SearchBar.css";

class SearchBar extends React.Component {
	render() {
		return (
			<div className="SearchBar">
				<input placeholder="Enter A Song, Album, or Artist" />
				<button className="SearchButton">SEARCH</button>
			</div>
		);
	}
}

export default SearchBar;


SearchResults.js

import React from "react";
import TrackList from "../TrackList/TrackList";
import "./SearchResults.css";

class SearchResults extends React.Component {
	render() {
		return (
			<div className="SearchResults">
				<h2>Results</h2>
				<TrackList
					tracks={this.props.searchResults}
					onAdd={this.props.onAdd}
					isRemoval={false}
				/>
			</div>
		);
	}
}

export default SearchResults;



Track.js

import React from "react";
import "./Track.css";

class Track extends React.Component {
	constructor(props) {
		super(props);
		this.addTrack = this.addTrack.bind(this);
	}

	renderAction() {
		if (this.props.isRemoval) {
			return <button className="Track-action">-</button>;
		} else {
			return (
				<button className="Track-action" onClick={this.addTrack}>
					+
				</button>
			);
		}
	}

	addTrack() {
		this.props.onAdd(this.props.track);
	}

	render() {
		return (
			<div className="Track">
				<div className="Track-information">
					<h3>{this.props.track.name}</h3>
					<p>
						{this.props.track.artist} | {this.props.track.album}
					</p>
				</div>
				{this.renderAction()}
			</div>
		);
	}
}

export default Track;


TrackList.js

import React from "react";
import "./TrackList.css";
import Track from "../Track/Track";

class TrackList extends React.Component {
	render() {
		return (
			<div className="TrackList">
				{this.props.tracks.map((track) => {
					return (
						<Track track={track} key={track.id} onAdd={this.props.onAdd} />
					);
				})}
			</div>
		);
	}
}

export default TrackList;

I’m not sure if this is what’s causing the problem you’re facing, but I was able to get the white screen of death and I think the cause is the following line in App.js, in the addTrack function:

const playlistUpdate = this.state.playlistTracks.push(track);

Instead of doing that, try assigning the playlistUpdate constant, and adding the track separately.

const playlistUpdate = this.state.playlistTracks;
playlistUpdate.push(track);

I was able to get it working. Maybe it will for you as well.

I should point out that the following line does not assign an array, but a number instead:

const playlistUpdate = this.state.playlistTracks.push(track); // length of new array, not an array

That’s because push() is called last in the statement, which returns the length of the new array, not the array itself.

1 Like

@richard-n super thank you! It seems so obvious now but it really stumped me for a while :joy:

Hi @henrybarnett and @richard-n, I just wanted to bump this thread and say thank you to you both. This finally got me past step 47 after three or four hours of bug hunting.

For reference, here’s the code provided by the walkthrough video:

addTrack(track) {
        let tracks = this.state.playlisttracks;
        if (tracks.find(savedTrack => savedTrack.id === track.id)) {
            return;
        }

        tracks.push(track);
        this.setstate({ playlisttracks: track });
    }

This code does not work as far as I can tell. This makes me think that the video is edited to remove unexpected errors which makes it very difficult to follow at times.

Regardless, here’s the code I used (thanks to you both) which works and is easier to understand in my opinion:

addTrack(track) {
        if (this.state.playlistTracks.includes(track.id)) {
            return;
        } else {
            const playlistUpdate = this.state.playlistTracks;
            playlistUpdate.push(track);
            this.setState({ playlistTracks: playlistUpdate });
        }
    }