React 在将两个映射数组渲染到页面时遇到问题

问题描述 投票:0回答:1

这里是非常新的 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;

我尝试为每个映射的返回值分配键,但没有任何效果。

javascript reactjs debugging rendering
1个回答
0
投票

看到您的代码后,我发现状态更新存在问题。

问题:当您第一次搜索流派时,数据将存储在

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;

如果您有任何疑问,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.