You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React useState数组移除异常:Playlist应用删除歌曲仅文本消失

播放列表歌曲移除后卡片残留问题的修复方案

问题描述

开发自定义播放列表应用时,搜索结果的歌曲可正常添加至播放列表,但点击移除按钮时,仅歌曲名、歌手、专辑文本消失,歌曲卡片仍保留在列表中。

问题根源及修复步骤

1. App组件中onRemove函数的数组处理错误

原代码里onRemove把filter返回的数组又套了一层数组,导致playlistTracks变成二维数组,渲染时出现空卡片项。

修正前的onRemove:

const onRemove = (e) => {
  console.log(playlistTracks);
  setPlaylistTracks([playlistTracks.filter((song) => song.id == e.id)]);
};

修正后的onRemove:

const onRemove = (track) => {
  setPlaylistTracks(prevTracks => prevTracks.filter(song => song.id !== track.id));
};

说明:

  • filter本身返回新数组,无需额外用[]包裹
  • 用函数式更新prevTracks,确保拿到最新状态值
  • 用!==替代==,避免隐式类型转换的潜在问题

2. Tracklist组件中key的错误生成方式

原代码每次渲染都随机生成key,导致React无法正确识别列表项变化,移除后DOM更新异常。

修正前的Tracklist map部分:

{props.tracks.map((track) => {
  return (
    <Track
      key={generateKey()}
      track={track}
      onAdd={props.onAdd}
      onRemove={props.onRemove}
      string={props.string}
    />
  );
})}

修正后的Tracklist map部分:

{props.tracks.map((track) => {
  return (
    <Track
      key={track.id}
      track={track}
      onAdd={props.onAdd}
      onRemove={props.onRemove}
      string={props.string}
    />
  );
})}

说明:

  • 用歌曲的唯一id作为key,React能通过key准确追踪列表项状态,确保移除后DOM正确更新
  • 删除Tracklist中冗余的generateKey函数,歌曲本身已有唯一id

完整修正后的代码片段

App组件修正后

import { useState } from "react";
import SearchBar from "./SearchBar";
import SearchResults from "./SearchResults";
import Playlist from "./Playlist";
import styles from "../Styles/App.module.css";

const generateKey = () => {
  let num = "";
  let characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  const chars = characters.length;

  for (let i = 0; i < 5; i++) {
    num += characters.charAt(Math.floor(Math.random() * chars));
  }

  return num;
};

function App() {
  const [playlistTracks, setPlaylistTracks] = useState([]);
  const [searchResults, setSearchResults] = useState([
    {
      song: "Go Baby",
      artist: "Lupe",
      album: "Food and Liqour",
      id: generateKey(),
    },
    {
      song: "Demon Days",
      artist: "Gorillaz",
      album: "Self titled",
      id: generateKey(),
    },
  ]);

  const onAdd = (track) => {
    setPlaylistTracks((prevTracks) => [...prevTracks, track]);
  };

  const onRemove = (track) => {
    setPlaylistTracks(prevTracks => prevTracks.filter(song => song.id !== track.id));
  };

  return (
    <div id={styles.app}>
      <header>
        <h1>Spotify Playlist App</h1>
      </header>
      <SearchBar />
      <main>
        <SearchResults searchResults={searchResults} onAdd={onAdd} />
        <Playlist
          playlistTracks={playlistTracks}
          name="playlist"
          onRemove={onRemove}
        />
      </main>
    </div>
  );
}

export default App;

Tracklist组件修正后

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

function Tracklist(props) {
  return (
    <div>
      {props.tracks.map((track) => {
        return (
          <Track
            key={track.id}
            track={track}
            onAdd={props.onAdd}
            onRemove={props.onRemove}
            string={props.string}
          />
        );
      })}
    </div>
  );
}

export default Tracklist;

内容的提问来源于stack exchange,提问作者shimmyshimmyya7347

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:07:03