React渲染映射数组异常:搜索流派按钮二次点击失效求助
React调用Spotify API二次点击「搜索流派」无响应问题修复
我是React新手,开发了一个调用Spotify API展示专辑的应用。当前遇到的问题是:首次点击「搜索流派」按钮可正常工作,点击「搜索新音乐」按钮也正常,但再次点击「搜索流派」按钮时毫无反应。已尝试为映射返回的每个元素添加key,但问题仍未解决,代码如下:
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;
问题分析与修复方案
核心问题
- 异步代码混用+无错误捕获:
searchGenre中混合使用await和.then(),且未处理API请求错误,一旦请求失败会抛出未捕获异常,导致后续点击无响应。 - URL未编码:搜索关键词直接拼接进URL,若包含空格、引号等特殊字符会破坏请求格式,触发API错误。
- 状态变量拼写错误:
setAcessToken少写了字母c,虽不影响首次请求,但存在潜在隐患。 - 表单默认提交行为:输入框所在表单未阻止默认提交,用户按回车会刷新页面重置状态。
具体修复代码
1. 修正searchGenre函数(统一异步逻辑+错误捕获+URL编码)
async function searchGenre() { try { // 对搜索关键词编码,避免特殊字符破坏URL结构 const encodedGenre = encodeURIComponent(searchInput); const response = await fetch( `https://api.spotify.com/v1/search?type=track&q=genre:"${encodedGenre}"&limit=50`, { headers: { Authorization: `Bearer ${accessToken}`, }, } ); // 检查API响应状态,非2xx状态抛出错误 if (!response.ok) { throw new Error(`请求失败:${response.status} ${response.statusText}`); } const data = await response.json(); setGenreAlbums(data.tracks.items); // 直接打印返回数据,React状态更新是异步的,无法立即获取新值 console.log("搜索到的流派曲目:", data.tracks.items); } catch (error) { console.error("搜索流派出错:", error); // 可在此添加用户可见的错误提示,比如弹窗或页面文字提示 } }
2. 修正状态变量拼写
// 初始化状态时修正拼写 const [accessToken, setAccessToken] = useState(""); // useEffect中对应修改状态设置函数 useEffect(() => { 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) => setAccessToken(data.access_token)); }, []);
3. 阻止表单默认提交行为
<form className="form" onSubmit={(e) => e.preventDefault()}> <input type="text" id="genre" autoComplete="off" onChange={(event) => setSearchInput(event.target.value)} /> </form>
4. 优化key值(避免使用索引)
用数据的唯一ID作为key,提升渲染性能并避免状态混乱:
// 新专辑列表 {albums.map((album) => ( <div className="card" key={album.id}> <img src={album.images[0].url} alt={album.name} /> <div className="container"> <h4><b>{album.name}</b></h4> <p>{album.artists[0].name}</p> </div> </div> ))} // 流派曲目列表 {genreAlbums.map((track) => ( <div className="card" key={track.id}> <img src={track.album.images[0].url} alt={track.name} /> <div className="container"> <h4><b>{track.name}</b></h4> <p>{track.artists[0].name}</p> </div> </div> ))}
内容的提问来源于stack exchange,提问作者Coleman Kuseliauskas
相关产品推荐
相关产品推荐

