这里是非常新的 React 用户。我正在制作一个反应应用程序,显示来自 Spotify API 的专辑。问题是,当您点击搜索流派按钮时,它会起作用,然后当您点击搜索新音乐按钮时,它会起作用,但当您再次尝试使用搜索流派按钮时,什么也没有发生。我的代码可能很粗糙,但就是这样。
import { useEffect, useState } from "react";
import "./App.css";
const CLIENT_ID = "2a65aa062a2948b09f7af884b5447c3d";
const CLIENT_SECRET = "e93fd764678a4ebe97accd512e302219";
function App() {
const [accessToken, setAcessToken] = useState("");
const [albums, setAlbums] = useState([]);
const [genreAlbums, setGenreAlbums] = useState([]);
const [searchInput, setSearchInput] = useState("");
useEffect(() => {
// API Acess Token
var authParameters = {
method: "POST",
headers: {
"content-type": "application/x-www-form-urlencoded",
},
body:
"grant_type=client_credentials&client_id=" +
CLIENT_ID +
"&client_secret=" +
CLIENT_SECRET,
};
fetch("https://accounts.spotify.com/api/token", authParameters)
.then((result) => result.json())
.then((data) => setAcessToken(data.access_token));
}, []);
// Get new music
async function search() {
var newAlbums = await fetch(
"https://api.spotify.com/v1/browse/new-releases",
{
headers: {
Authorization: "Bearer " + accessToken,
},
}
)
.then((response) => response.json())
.then((data) => setAlbums(data.albums.items));
}
// Get specific genre
async function searchGenre() {
var newAlbumsGenre = await fetch(
'https://api.spotify.com/v1/search?type=track&q=genre:"' +
searchInput +
'"&limit=50',
{
headers: {
Authorization: "Bearer " + accessToken,
},
}
)
.then((response) => response.json())
.then((data) => setGenreAlbums(data.tracks.items));
console.log(genreAlbums);
}
return (
<div className="App">
<div>
<button className="button" type="button" onClick={search}>
Search for new music!
</button>
<form className="form">
<input
type="text"
id="genre"
autoComplete="off"
onChange={(event) => setSearchInput(event.target.value)}
/>
</form>
<button className="genreButton" type="button" onClick={searchGenre}>
Search Genre
</button>
</div>
<div>
{albums.map((album, i) => {
return (
<div className="card" key={i}>
<img src={album.images[0].url} alt="alt text" />
<div className="container">
<h4>
<b>{album.name}</b>
</h4>
<p>{album.artists[0].name}</p>
</div>
</div>
);
})}
</div>
<div>
{genreAlbums.map((track, i) => {
return (
<div className="card" key={i}>
<img src={track.album.images[0].url} alt="alt text" />
<div className="container">
<h4>
<b>{track.name}</b>
</h4>
<p>{track.artists[0].name}</p>
</div>
</div>
);
})}
</div>
</div>
);
}
export default App;
我尝试为每个映射的返回值分配键,但没有任何效果。
看到您的代码后,我发现状态更新存在问题。
问题:当您第一次搜索流派时,数据将存储在
genreAlbums
状态。比你渲染两个不同的 div 与流派和音乐。
现在,在搜索流派后,您正在搜索将存储在
albums
中的音乐,但此时 GenreAlbums 仍然不为空,这将导致这种意外的行为。
解决方案: 创建一个状态来跟踪您单击的搜索。
这是更新后的代码(链接):
import { useEffect, useState } from "react";
const CLIENT_ID = "2a65aa062a2948b09f7af884b5447c3d";
const CLIENT_SECRET = "e93fd764678a4ebe97accd512e302219";
function App() {
const [accessToken, setAcessToken] = useState("");
const [albums, setAlbums] = useState([]);
const [genreAlbums, setGenreAlbums] = useState([]);
const [searchInput, setSearchInput] = useState("");
const [currentsearch, setCurrentSearch] = useState("");
useEffect(() => {
// API Acess Token
var authParameters = {
method: "POST",
headers: {
"content-type": "application/x-www-form-urlencoded",
},
body:
"grant_type=client_credentials&client_id=" +
CLIENT_ID +
"&client_secret=" +
CLIENT_SECRET,
};
fetch("https://accounts.spotify.com/api/token", authParameters)
.then((result) => result.json())
.then((data) => setAcessToken(data.access_token));
}, []);
// Get new music
async function search() {
var newAlbums = await fetch(
"https://api.spotify.com/v1/browse/new-releases",
{
headers: {
Authorization: "Bearer " + accessToken,
},
},
)
.then((response) => response.json())
.then((data) => setAlbums(data.albums.items));
setCurrentSearch("music");
}
// Get specific genre
async function searchGenre() {
var newAlbumsGenre = await fetch(
'https://api.spotify.com/v1/search?type=track&q=genre:"' +
searchInput +
'"&limit=50',
{
headers: {
Authorization: "Bearer " + accessToken,
},
},
)
.then((response) => response.json())
.then((data) => setGenreAlbums(data.tracks.items));
setCurrentSearch("genre");
}
return (
<div className="App">
<div>
<button className="button" type="button" onClick={search}>
Search for new music!
</button>
<form className="form">
<input
type="text"
id="genre"
autoComplete="off"
onChange={(event) => setSearchInput(event.target.value)}
/>
</form>
<button className="genreButton" type="button" onClick={searchGenre}>
Search Genre
</button>
</div>
{currentsearch === "music" ? (
<div>
{albums.map((album, i) => {
return (
<div className="card" key={i}>
<img src={album.images[0].url} alt="alt text" />
<div className="container">
<h4>
<b>{album.name}</b>
</h4>
<p>{album.artists[0].name}</p>
</div>
</div>
);
})}
</div>
) : (
<div>
{genreAlbums.map((track, i) => {
return (
<div className="card" key={i}>
<img src={track.album.images[0].url} alt="alt text" />
<div className="container">
<h4>
<b>{track.name}</b>
</h4>
<p>{track.artists[0].name}</p>
</div>
</div>
);
})}
</div>
)}
</div>
);
}
export default App;
如果您有任何疑问,请告诉我。