Reputation: 263
I am making a React.js app that uses an audio player to play a snippet of a song depending on what the user selects. However I realize that when I go to run the application, the audio never loads. So the first thing I did was make sure that I was receiving a URL back from the server in general. Once I verified that, I was thinking that maybe I need a npm package
to do that work for me instead. Though I also tried two npm packages and they didn't give me what I wanted it terms of end result. So I am still trying to figure out why the audio tag did not work the first time and why it was disabled.
Code:
import React, { useState, useEffect } from 'react';
import Aux from '../../hoc/Aux';
import Navbar from './Navbar';
import WeekSelection from './WeekSelection';
import axios from 'axios';
const Landing = () => {
//useState to set up information
const [formData, setFormData] = useState({
name: '',
artist: '',
album: '',
duration: '',
image: '',
url: '',
day: null
});
const [numberCharts, setNumberCharts] = useState({
numberOne: {
name: null,
artist: null
},
numberTwo: {
name: null,
artist: null
},
numberThree: {
name: null,
artist: null
},
numberFour: {
name: null,
artist: null
},
numberFive: {
name: null,
artist: null
}
});
useEffect(() => {
axios.post("/")
.then(res => {
console.log(res);
let days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
let dayOfWeek = days[new Date().getDay()];
console.log("URL",res.data.url);
setFormData({
name: res.data.name,
artist: res.data.artist,
album: res.data.album,
duration: res.data.duration,
image: res.data.image,
url: res.data.url,
day: dayOfWeek
});
setNumberCharts({
numberOne: {
name: res.data.topFive.numberOne.name,
artist: res.data.topFive.numberOne.artist
},
numberTwo: {
name: res.data.topFive.numberTwo.name,
artist: res.data.topFive.numberTwo.artist
},
numberThree: {
name: res.data.topFive.numberThree.name,
artist: res.data.topFive.numberThree.artist
},
numberFour: {
name: res.data.topFive.numberFour.name,
artist: res.data.topFive.numberFour.artist
},
numberFive: {
name: res.data.topFive.numberFive.name,
artist: res.data.topFive.numberFive.artist
}
});
})
.catch(err => {
console.error(err.message);
});
}, []);
return (
<Aux>
<Navbar />
<div className="myLeft">
<div className="company-name">
<span className="headphones">
<i className="fas fa-headphones"></i>
</span>
<h1 className="titleStyle">SilverStone</h1>
</div>
<WeekSelection currentRank="NO. 1" song={numberCharts.numberOne.name} artist={numberCharts.numberOne.artist}/>
<WeekSelection currentRank="NO. 2" song={numberCharts.numberTwo.name} artist={numberCharts.numberTwo.artist}/>
<WeekSelection currentRank="NO. 3" song={numberCharts.numberThree.name} artist={numberCharts.numberThree.artist}/>
<WeekSelection currentRank="NO. 4" song={numberCharts.numberFour.name} artist={numberCharts.numberFour.artist}/>
<WeekSelection currentRank="NO. 5" song={numberCharts.numberFive.name} artist={numberCharts.numberFive.artist}/>
</div>
<div className="myRight">
<div className="test">
<img src={formData.image} alt="Spotify Cover Art" />
</div>
<div className="song-data">
<h2 className="week">{formData.day}</h2>
<div className="song-box-data">
{/* <div className="rectangle-1"></div> */}
<p className="song-styles">Song</p>
{/* <div className="music-icon"></div> */}
</div>
<div className="seeYouAgain">{formData.name}</div>
<div className="artist-line">
<div className="by">By: {formData.artist}</div>
{/* <div className="artist-line-name">{formData.artist}</div> */}
</div>
<div className="time-info">
<div className="duration">Duration</div>
<div className="minutes">{formData.duration} Min</div>
{/* <div className="clock">
<i className="far fa-clock"></i>
</div> */}
</div>
<audio controls preload="auto">
<source src={formData.url} type="audio/mp3"/>
</audio>
</div>
</div>
</Aux>
)
};
export default Landing;
URL:
https://p.scdn.co/mp3-preview/8db0f8fc6607d9760f1ac26f0d7d54b1c458b9ac?cid=907576181422448e91e222b424ba898a
When I put the URL in manually it works fine, but when I do it dynamically it does NOT work.
Upvotes: 0
Views: 1759
Reputation: 10127
You're juggling the mp3 file referenced by the audio control, but you aren't triggering a load. The issue is that unlike a lot of static HTML, the audio control is stateful, and even if preset is on, that only controls it's behavior at full page load.
You need to use another hook to update its state in the browser:
const AudioControl = ({url}) => {
//We're pulling this by ID - use the uuid library to avoid collisions if you have multiple
const controlId = "use-uuid-if-multiple-on-page";
useEffect(() => {
const audioControl = document.querySelector(`#${controlId}`);
if(audioControl) {
//Register the changed source
audioControl.load();
}
})
return <audio id={controlId} controls preload="auto">
<source src={url} type="audio/mpeg"/>
</audio>
}
That makes for a self contained control that will update itself whenever the url changes as a prop.
Upvotes: 2
Reputation: 3145
Try audio/mpeg
vs audio/mp3
i.e
<audio controls preload="auto">
<source src={formData.url} type="audio/mpeg"/>
</audio>
Upvotes: -1