kane_004
kane_004

Reputation: 263

Fix Audio tag in html not working in React

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

Answers (2)

Dan Monego
Dan Monego

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

Ramakay
Ramakay

Reputation: 3145

Try audio/mpeg vs audio/mp3

i.e

    <audio controls preload="auto">
                <source src={formData.url} type="audio/mpeg"/>
            </audio>

Upvotes: -1

Related Questions