我正在尝试制作一个播放列表应用程序,您可以在其中使用搜索结果创建您自己的播放列表。我已经成功地将搜索结果中的歌曲传递到播放列表,但是当我尝试删除它们时,我无法删除整个卡。相反,只有艺术家、歌曲和专辑消失,但卡片仍保留在列表中。
正如您所看到的,在我单击删除按钮后,卡片仍然存在,但其文本消失了。
这就是我的文件的样子
顶级应用程序组件
import { useState, useCallback } 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 = (e) => {
console.log(playlistTracks);
setPlaylistTracks([playlistTracks.filter((song) => song.id == e.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;
这是我的播放列表组件
import React, { useState } from "react";
import styles from "../Styles/Playlist.module.css";
import Tracklist from "./Tracklist";
function Playlist(props) {
const { playlistTracks } = props;
const [name, setName] = useState("Playlist");
const nameList = (e) => {
e.preventDefault();
setName(e.target.value);
};
return (
<div id={styles.playlist}>
<h3>{name}</h3>
<input onChange={nameList} type="text" />
<Tracklist
tracks={playlistTracks}
string="playlist"
onRemove={props.onRemove}
/>
<button>Save to Spotify</button>
</div>
);
}
export default Playlist;
曲目列表组件
import React from "react";
import Track from "./Track";
function Tracklist(props) {
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;
};
return (
<div>
{props.tracks.map((track) => {
return (
<Track
key={generateKey()}
track={track}
onAdd={props.onAdd}
onRemove={props.onRemove}
string={props.string}
/>
);
})}
</div>
);
}
export default Tracklist;
轨道组件
import React, { useCallback } from "react";
import styles from "../Styles/Track.module.css";
function Track(props) {
const string = props.string;
const choice = () => {
switch (string) {
case "search": {
return <button onClick={() => props.onAdd(props.track)}>+</button>;
}
case "playlist": {
return <button onClick={() => props.onRemove(props.track)}>-</button>;
}
default: {
return undefined;
}
}
};
return (
<div id={styles.track}>
<div id={styles.track_info}>
<h4>{props.track.song}</h4>
<p>
{props.track.artist} | {props.track.album}
</p>
</div>
{choice()}
</div>
);
}
export default Track;
我尝试从搜索结果中删除添加的卡片,但无济于事
您的
onRemove()
函数可能编码不正确。
setPlaylistTracks([playlistTracks.filter((song) => song.id == e.id)]);
这将在每次调用时创建一个数组的数组。
playlistTracks.filter()
的结果将是一个数组,然后创建一个具有 playlistTracks.filter()
结果的单成员数组,即一个数组的数组。相反,请考虑删除外部数组构造函数:
setPlaylistTracks(playlistTracks.filter((song) => song.id == e.id));
此外,由于该函数被命名为
onRemove
,看起来您可能正在从状态中删除通过的轨迹。目前,这将排除除通过的轨道之外的所有其他轨道。考虑将 filter()
回调中的逻辑反转为(严格)不等于 (!==
):
setPlaylistTracks(playlistTracks.filter((song) => song.id !== e.id));
最后,为了防止任何可能的过时状态,请考虑将函数传递给
setPlaylistTracks
。该函数将接收最新状态并返回新状态:
setPlaylistTracks((tracks) => tracks.filter((song) => song.id !== e.id));
const { useState, useCallback } = React;
function Playlist(props) {
const { playlistTracks } = props;
const [name, setName] = useState("Playlist");
const nameList = (e) => {
e.preventDefault();
setName(e.target.value);
};
return (
<div id={styles.playlist}>
<h3>{name}</h3>
<input onChange={nameList} type="text" />
<Tracklist
tracks={playlistTracks}
string="playlist"
onRemove={props.onRemove}
/>
<button>Save to Spotify</button>
</div>
);
}
function Tracklist(props) {
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;
};
return (
<div>
{props.tracks.map((track) => {
return (
<Track
key={generateKey()}
track={track}
onAdd={props.onAdd}
onRemove={props.onRemove}
string={props.string}
/>
);
})}
</div>
);
}
const styles = {
track: 'track',
track_info: 'track_info',
};
function Track(props) {
const string = props.string;
const choice = () => {
switch (string) {
case "search": {
return <button onClick={() => props.onAdd(props.track)}>+</button>;
}
case "playlist": {
return <button onClick={() => props.onRemove(props.track)}>-</button>;
}
default: {
return undefined;
}
}
};
return (
<div id={styles.track}>
<div id={styles.track_info}>
<h4>{props.track.song}</h4>
<p>
{props.track.artist} | {props.track.album}
</p>
</div>
{choice()}
</div>
);
}
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;
};
const SearchBar = () => 'SearchBar';
const SearchResults = ({ searchResults, onAdd }) => (
<React.Fragment>
{searchResults.map(result => (
<button onClick={() => onAdd(result)}>
{result.song}
</button>
))}
</React.Fragment>
);
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 = (e) => {
console.log(playlistTracks);
setPlaylistTracks(tracks => tracks.filter((song) => song.id !== e.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>
);
}
ReactDOM.createRoot(document.getElementById('app')).render(<App/>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app"></div>