我目前正在基于创建Spotify播放列表进行React应用程序练习。这是主要的代码库:

App.js

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

const track = {
  name: "Hello",
  artist: "Again",
  album: "Friend of a friend",
  id: 0
};

const tracks = [track, track, track];

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      searchResults: tracks,
      playlistName: "DEFAULT",
      playlistTracks: tracks
    };
    this.addTrack = this.addTrack.bind(this);
    this.removeTrack = this.removeTrack.bind(this);
  }

  addTrack(track) {
    this.state.playlistTracks.map(id => {
      if(track.id === id)
        return;
    });
    this.setState((state, track) => ({
      playlistTracks: state.playlistTracks.push(track)
    }));
  }

  removeTrack(track) {
    this.state.playlistTracks.map(id => {
      if(track.id === id)
        {
          this.setState((state, track) => ({
            playlistTracks: state.playlistTracks.remove(track)
          }));
        }
    });
  }

  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 name= {this.state.playlistName} tracks= {this.state.playlistTracks} onRemove= {this.removeTrack}/>
        </div>
      </div>
    </div>
  );
  }
}

export default App;


Playlist.js


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

function Playlist(props) {
    return (
        <div className="Playlist">
        <input value="New Playlist"/>
        <button className="Playlist-save">SAVE TO SPOTIFY</button>
        <TrackList tracks= {props.tracks} onRemove= {props.onRemove} isRemoval= {true}/>
        </div>
    );
}

export default Playlist;


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

function SearchBar () {
        return (
            <div className="SearchBar">
            <input placeholder="Enter A Song, Album, or Artist" />
            <button className="SearchButton">SEARCH</button>
            </div>
        );
}

export default SearchBar;


SearchBar.js

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

function SearchBar () {
        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 './SearchResults.css';
import TrackList from '../TrackList/TrackList';

function SearchResults (props) {
        return (
            <div className="SearchResults">
            <h2>Results</h2>
            <TrackList tracks={props.searchResults} onAdd= {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);
        this.removeTrack = this.addTrack.bind(this);
    }

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

    removeTrack() {
        this.props.onRemove(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 onClick= {this.addTrack}>+</div>
                        <div onClick= {this.removeTrack}>-</div>
                    </div>
            </div>
        );
}
}

export default Track;


TrackList.js

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

function TracklList (props) {
        return (
            <div className="TrackList">
            {
                props.tracks.map(track => {
                    return <Track
                        track={track}
                        key={track.id}
                        onAdd= {props.onAdd}
                        onRemoval= {props.onRemoval}
                        isRemove= {props.isRemove}
                    />;
                })
            }
            </div>
        );
}

export default TracklList;


目前,这是一个非常基础的应用程序,但到目前为止,我仍在尝试测试某些功能。我正在尝试测试将结果部分中的歌曲添加到播放列表中的过程。但是,当我单击其中一首歌曲上的加号图标时,出现以下错误:

javascript - TypeError:props.tracks.map不是函数-LMLPHP

该错误仅在单击加号图标后才弹出,因此我的最初假设是将状态对象从数组更改为列表。但是,我不知道这是怎么回事。无论如何,到目前为止,我绝对可以使用第二种意见!

最佳答案

Array.push更改调用数组,并返回一个数字,指示新数组的长度。

在您的addTrack方法中,旧的playlistTracks状态被突变,新状态被设置为数字而不是新数组。

使用传播语法以不变的方式将新项目添加到数组中。

同样,setState接受新状态,或者接受旧状态并返回新状态的函数,也应从addTrack方法接收跟踪

P / S:setState上方的.map似乎无法按预期工作。

addTrack(track) {
    /*
     * NOTE: the code below doesn't affect anything since `map`
     * will be applied on each item and does not stop when you `return`
     * also, it seems like `playlistTracks` is an array of object, but was
     * used as an array of string here
     */
    this.state.playlistTracks.map(id => {
        if (track.id === id)
            return;
    });
    this.setState((state/* ,track -- I think this should be removed */) => ({
        // old code: playlistTracks: state.playlistTracks.push(track)
        playlistTracks: [...state.playlistTracks, track]
    }));
}

09-25 16:47
查看更多