在状态下反应本机更新数组

时间:2020-01-23 14:39:14

标签: react-native

我正在开发一个应用程序,该应用程序内置了歌曲和播放列表。用户应该能够将歌曲添加到播放列表中。

以下是歌曲和播放列表的模型: 播放列表:

class Playlist {
  id: number;
  name: String;
  color: String;
  songs: Song[];
  constructor(id: number, name: String, color: String) {
    this.id = id;
    this.name = name;
    this.color = color;
    this.songs = [];
  }
}

歌曲:

class Song {
  id: number;
  artist: String;
  title: String;
  constructor(id: number, artist: String, title: String) {
    this.id = id;
    this.artist = artist;
    this.title = title;
  }
}

这是“播放列表”屏幕(初始屏幕):

export default class Playlists extends Component<Props, State> {
  constructor(props) {
    super(props);
    this.state = {
      playlists: [
        new Playlist(0, 'Favorite Songs', 'purple'),
        new Playlist(1, 'Rock', 'green'),
        new Playlist(2, 'Pop', 'blue'),
        new Playlist(3, 'Electronic', 'yellow'),
      ],
    };
  }

  render() {
    const {navigation} = this.props;

    return (
      <FlatList
        data={this.state.playlists}
        renderItem={({item: playlist}) => (
          <TouchableOpacity
            onPress={() =>
              navigation.navigate('PlaylistDetails', {
                playlist: playlist,
                //Pass method to next screen, to be able to update songs
                onAddSongs: (songs: Song[]) => {
                   //Update songs in this particular playlist
                },
              })
            }>
            <Text style={styles.text}>{playlist.name}</Text>
            <Text style={styles.count}>{playlist.songs.length}</Text>  //This field should get updated
          </TouchableOpacity>
        )}
      />
    );
  }
}

按下播放列表项时,它将导航到“播放列表详细信息”屏幕:

export default class PlaylistDetails extends Component<Props, State> {
  constructor(props) {
    super(props);
    this.state = {
      playlist: this.props.navigation.getParam('playlist'),
    };
  }

  render() {
    const {navigation} = this.props;

    return (
      <View>
        <Text>{this.state.playlist.name}</Text>
        <FlatList
          data={this.state.playlist.songs}
          renderItem={({item: song}) => <Text>{song.title}</Text>}
        />
        <Button
          title="Add Songs"
          onPress={() =>
            navigation.navigate('AddSongs', {
              addedSongs: this.state.playlist.songs,
              onAddSongs: (selectedSongs: Song[]) => {
                var newPlaylist = this.state.playlist;
                newPlaylist.songs = selectedSongs;
                //Update songs in this screen
                this.setState(
                  (this.state = {
                    playlist: newPlaylist,
                  }),
                );
                navigation.getParam('onAddSongs')(selectedSongs); //This method i called to pass the songs further to the Playlists screen
              },
            })
          }
        />
      </View>
    );
  }
}

按下“添加歌曲”按钮时,它将导航到“添加歌曲”屏幕:

export default class AddSongs extends Component<Props, State> {
  constructor(props) {
    super(props);
    this.state = {
      selectedSongs: this.props.navigation.getParam('addedSongs'),
    };
  }

  songs = [
    new Song(0, 'Avicii', 'Heaven'),
    new Song(1, 'Shakira', 'Waka Waka'),
    new Song(2, 'Post Malone', 'Circles'),
    new Song(3, 'Katy Perry', 'Dark Horse'),
    new Song(4, 'Ed Sheeran', 'Shape of You'),
    new Song(5, 'Maroon 5', 'Sugar'),
    new Song(6, 'Adele', 'Hello'),
    new Song(7, 'OneRepublic', 'Counting Stars'),
    new Song(8, 'Queen', 'Bohemian Rhapsody'),
    new Song(9, 'Deep Purple', 'Smoke On The Water'),
    new Song(10, 'Nirvana', 'Smells Like Teen Spirit'),
    new Song(11, 'Steppenwolf', 'Born To Be Wild'),
    new Song(12, 'Kina', 'Get You the Moon'),
    new Song(13, 'Petit Biscuit', 'Sunset Lover'),
    new Song(14, 'Avicii', 'Levels'),
    new Song(15, 'Avicii', 'Wake Me Up'),
  ];

  render() {
    const {navigation} = this.props;
    const onAddSongs = navigation.getParam('onAddSongs');

    return (
      <View>
        <FlatList
          data={this.songs}
          renderItem={({item: song}) => (
            <TouchableOpacity
              style={styles.songItem}
              onPress={() => {
                //Check if song is already added. If yes, remove song from selectedSongs. If not, add it.
                if (
                  this.state.selectedSongs.filter(
                    addedSong => addedSong.id == song.id,
                  ).length > 0
                ) {
                  this.setState(
                    (this.state = {
                      selectedSongs: this.state.selectedSongs.filter(
                        addedSong => addedSong.id != song.id,
                      ),
                    }),
                  );
                } else {
                  var newSelectedSongs = this.state.selectedSongs;
                  newSelectedSongs.push(song);
                  this.setState(
                    (this.state = {selectedSongs: newSelectedSongs}),
                  );
                }
              }}>
              <Text style={styles.text}>
                Title: {song.title}, Artist: {song.artist}
              </Text>
              //Show the below Vie only if the song is added to selectedSongs
              {this.state.selectedSongs.filter(
                addedSong => addedSong.id == song.id,
              ).length > 0 && <View style={styles.selectedIndicator} />}
            </TouchableOpacity>
          )}
        />
        <Button
          title="Add Songs"
          onPress={() => {
            onAddSongs(this.state.selectedSongs);
            navigation.goBack();
          }}
        />
      </View>
    );
  }
}

Playlists类中,我不知道要放在onAddSongs方法中的内容。我想我必须调用setState()才能再次呈现UI,因为我想更新添加的歌曲的计数。但是在setState()中,我必须将新值设置为this.state.playlists,所以我将不得不创建一个新的播放列表数组。 我习惯于用Java开发,对Javascript和Typescript还是陌生的,所以我真的不知道该怎么做。顺便说一句,如果我的代码包含任何其他缺陷,我欢迎您提出建议。如前所述,我是新来的本地人。

谢谢

0 个答案:

没有答案