Jammming project, react. Getting error: Functions are not valid as a React child

Hello, I am currently working on the jammming project in the react section. Here is the link to the project:
Jammming Project

I finished the last step and ran my project. However I am getting this error. Please see the image:

It says “Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it”.

Then it lists 4 lines that are causing this error. Here are the lines:

  1. at Track (http://localhost:3000/static/js/main.chunk.js:1334:5). Here is the code it is referring to:
export class Track extends React.Component{
    constructor(props){
        super(props); **//<--this is the line the error is referring to**
        this.addTrack = this.addTrack.bind(this);
        this.removeTrack=this.removeTrack.bind(this);
        this.renderAction = this.renderAction.bind(this);
    }

2.at Tracklist (http://localhost:3000/static/js/main.chunk.js:1609:1). Here is the code referring to:

export class Tracklist extends React.Component{ **//<--The error refers to this line**
    render() {
        return (
    <div className="TrackList">
             <Track track = {this.props.tracks.map(track=> track.id)}
              onAdd={this.props.onAdd} isRemoval={this.props.isRemoval} 
              onRemove={this.props.removeTrack} />
    </div>
        );
    }
}
  1. at SearchResults (http://localhost:3000/static/js/main.chunk.js:1112:1). Here is the code it refers to:
export class SearchResults extends React.Component{ //<-- The error refers to this line
    render(){
        return (
            <div className="SearchResults">
                <h2>Results</h2>
                {/*<!-- Add a TrackList component -->*/}
                    <Tracklist tracks = {this.props.searchResults} onAdd={this.props.onAdd} isRemoval = {false} />
            </div>
        );
    }
}
  1. at App (http://localhost:3000/static/js/main.chunk.js:288:5). Here is the code it refers to:
export class App extends React.Component{
  constructor(props){
    super(props); //<--The error refers to this line
    this.state = {searchResults:[{name:'',artist:'',album:'',id:''}],
                  playlistName:'',
                  playlistTracks:[{name:'',artist:'',album:'',id:''}],
                  searchTerm:''
                  };
    this.addTrack= this.addTrack.bind(this);
    this.removeTrack=this.removeTrack.bind(this);
    this.updatePlaylistName=this.updatePlaylistName.bind(this);
    this.savePlaylist=this.savePlaylist.bind(this);
    this.search=this.search.bind(this);
    this.searchResults=this.searchResults.bind(this);
  }

I think I may be passing the functions wrong to the Components

Here is my App.js code where I pass properties to the other components:

  render(){
    return (
      <div>
        <h1>Ja<span className="highlight">mmm</span>ing</h1>
        <div className="App">
          {/*<!-- Add a SearchBar component -->*/}
            <SearchBar onSearch={this.search} />
          <div className="App-playlist">
            {/*<!-- Add a SearchResults component -->*/}
              <SearchResults searchResults ={this.state.searchResults} onAdd={this.addTrack} />
            {/*<!-- Add a Playlist component -->*/}
              <Playlist playlistName={this.state.playlistName}
               playlistTracks={this.state.playlistTracks} onRemove={this.removeTrack}
               onNameChange={this.updatePlaylistName} onSave={this.savePlaylist} />
          </div>
        </div>
    </div>
      );
  }
}

I also could be passing properties wrong in SearchPlaylist.js:

export class SearchResults extends React.Component{
    render(){
        return (
            <div className="SearchResults">
                <h2>Results</h2>
                {/*<!-- Add a TrackList component -->*/}
                    <Tracklist tracks = {this.props.searchResults} onAdd={this.props.onAdd} isRemoval = {false} />
            </div>
        );
    }
}

Or I could be passing properties wrong to the Track component in Tracklist.js:

export class Tracklist extends React.Component{
    render() {
        return (
    <div className="TrackList">
    {/*<!-- You will add a map method that renders a set of Track components  -->*/}
             <Track track = {this.props.tracks.map(track=> track.id)}
              onAdd={this.props.onAdd} isRemoval={this.props.isRemoval} 
              onRemove={this.props.removeTrack} />
    </div>
        );
    }
}

I might be doing something wrong in Track.js:

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


export class Track extends React.Component{
    constructor(props){
        super(props);
        this.addTrack = this.addTrack.bind(this);
        this.removeTrack=this.removeTrack.bind(this);
        this.renderAction = this.renderAction.bind(this);
    }
    renderAction(){
        let isRemoval = this.props.isRemoval;
        if(isRemoval){
            return <button className="Track-action" onClick={this.removeTrack}>-</button>;
        }
        else if(!isRemoval){
            return <button className="Track-action" onClick={this.addTrack}>+</button>;
        }
    }
    addTrack(){
        const newTrack = this.props.track;
        this.props.onAdd(newTrack); //maybe I'm doing something wrong here.
    }
    removeTrack(){
        const removedTrack= this.props.track;
        this.props.onRemove(removedTrack); //maybe I'm doing something wrong here.
    }
    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>
                <button className="Track-action">{this.renderAction}</button>
                
            </div>
        );
    }
}

I’m not sure if I should be passing the functions as properties with ( ). For example:

<Playlist playlistName={this.state.playlistName}
               playlistTracks={this.state.playlistTracks} onRemove={this.removeTrack()}
               onNameChange={this.updatePlaylistName()} onSave={this.savePlaylist()} />

Any help is appreciated. I’ve been scouring the internet and can’t seem to find the solution. Well, take care everyone and happy coding :slight_smile:

Hi @codejumper03379

The component ‘Track’ receives invalid props.
That is because you’re calling the method .map() rather than passing a single object or a function as props to the Track component here:

You should render one Track component per track that is stored in this.props.tacks. Instead you render just one Track component and map the tracks in the attribute track of that component.

The output of the map() method should be something like this:

<div className="TrackList">
  <Track />
  <Track />
  <Track />
</div>

which means that you have to call map() outside of the <Track/> tag and return the <Track/> from the map() method instead.

3 Likes

@mirja_t thank you so much! Thanks for the clear explanation. I will go ahead and try it out. I really appreciate it. Take care and all the best :slight_smile:

1 Like

Thanks, this worked for me.

1 Like

thank u so much. this helps me

1 Like