React挂钩音乐播放器onClick始终播放同一首歌曲

时间:2019-08-21 21:45:00

标签: reactjs react-hooks

我正在尝试使用React Hooks编码音乐播放器。 该音乐播放器通过Deezer API提取乐队的前五首最著名的歌曲。

当我单击任意歌曲上的播放/暂停时,它总是播放同一首歌曲。

我知道问题出在useRef上,但我不知道该如何解决。 我阅读了许多教程和文章,但没有任何解决方法。有人可以帮忙吗?谢谢!

import React, { useState, useEffect } from 'react';
import './App.scss';

const BASE_URL = 'https://cors-anywhere.herokuapp.com/https://api.deezer.com/artist/182/top'

function MusicPlayer(){
  const [ songs, setSongs ] = useState([])
  const [ isLoading, setIsLoading ] = useState(false)
  const [ error, setError ] = useState(null)

  const inputRef = React.useRef()

  useEffect(() => {
    setIsLoading(true)
    fetch(BASE_URL, {headers: {
      "Accept": "application/json",
      "Access-Control-Allow-Origin": "*"
    }})
    .then (res => {
      return res.ok ? res.json() : throw new Error("Mistake!")
    })
    .then(songs => {
      setSongs(songs.data)
      setIsLoading(false)
    })
    .catch(error => {
      setError(error)
    })
    }, [])

  if (error){ return <p> { error.message }</p> }
  if (isLoading ){ return <p> Loading songs...</p> }

  return(
    <div>
      { songs.map( (song, i) => (
          <div key={i}>
            <h1>{song.title}</h1>
            <img src={song.contributors[0].picture_small}/><br/>
            <audio ref={inputRef} src={song.preview} />
            <button onClick={() => inputRef.current.play()}>Play</button>          
            <button onClick={() => inputRef.current.pause()}>Pause</button>
          </div>
          ))
      }
    </div>
    )
    }

export default MusicPlayer

1 个答案:

答案 0 :(得分:1)

这应该做您想要的:

import ReactDOM from "react-dom";
import React, { useState, useEffect } from "react";

const BASE_URL =
  "https://cors-anywhere.herokuapp.com/https://api.deezer.com/artist/182/top";

function MusicPlayer() {
  const [songs, setSongs] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  const [currentSong, setCurrentSong] = useState(null);
  const inputRef = React.useRef();

  useEffect(() => {
    if (currentSong) {
      inputRef.current.play();
    }
    console.log(currentSong);
  }, [currentSong]);

  useEffect(() => {
    setIsLoading(true);
    fetch(BASE_URL, {
      headers: {
        Accept: "application/json",
        "Access-Control-Allow-Origin": "*"
      }
    })
      .then(res => {
        return res.ok ? res.json() : null;
      })
      .then(songs => {
        setSongs(songs.data);
        setIsLoading(false);
      })
      .catch(error => {
        setError(error);
      });
  }, []);

  if (error) {
    return <p> {error.message}</p>;
  }
  if (isLoading) {
    return <p> Loading songs...</p>;
  }

  const handlePlay = songPreview => {
    if (currentSong) {
      if (currentSong === songPreview) {
        return inputRef.current.play();
      }
    }
    setCurrentSong(songPreview);
  };

  return (
    <div>
      {songs.map((song, i) => (
        <div key={i}>
          <h1>{song.title}</h1>
          <img src={song.contributors[0].picture_small} />
          <br />
          <audio ref={inputRef} src={currentSong} />
          <button onClick={() => handlePlay(song.preview)}>Play</button>
          <button onClick={() => inputRef.current.pause()}>Pause</button>
        </div>
      ))}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<MusicPlayer />, rootElement);

基本上,您需要跟踪当前正在播放的歌曲。

CodeSandbox演示here