0

I am creating an audio player in React and I have the following code. It plays fine when you click on the play button once but refuses to pause when you click pause. Also if you click play again, instead of just continuing the audio it creates new audio of the same song and plays it on top of the previous song. I'm not sure how to fix this.

const AudioPlayer = () => {
    let audio = new Audio(song)
    const [playing, setPlaying] = useState(false)

    const playHandler = () => {
        if(playing){
            setPlaying(false)
            console.log(playing)
        }
        else{
            setPlaying(true)
        }
    }

    const audioPause = () => {
        audio.pause()
        
    }

    const audioPlay = () => {
        audio.play()
    }

    useEffect (() => {
        (playing) ? audioPlay() : audioPause()
    }, [playing])

    return(
        <div className="songPlaying">
            <p> { (playing) ? "Now playing" : "Stopped Playing" } </p>
            <button type="submit" onClick={playHandler}> 
                {(playing) ? "Pause" : "Play" }
            </button>
        </div>
    )
}
Yoshi
  • 54,081
  • 14
  • 89
  • 103
Leila K.
  • 77
  • 6

2 Answers2

2

Instead creating a variable of audio, you can create a state of it, and update it accordingly.

Here is the sample code, this should work in your case:

...
//  let audio = new Audio(song)
const [audio] = useState(new Audio(song));
...

In your case, your code is creating a new object every time, when you hit pause and play so this is the reason why it overlapping the audio instead of pause and play.

By creating a state, it remains the same object, so whenever you're updating the state of play and pause, it can use the same audio object and do actions on it, rather than creating a new one.

Here is the minified code of yours:

const AudioPlayer = () => {
    const [audio] = useState(new Audio(song));
    const [playing, setPlaying] = useState(false)

    const toggle = () => setPlaying(!playing);

    useEffect(() => {
        playing ? audio.play() : audio.pause();
    },
        [playing]
    );
    return (
        <div className="songPlaying">
            <p> {(playing) ? "Now playing" : "Stopped Playing"} </p>
            <button type="submit" onClick={toggle}>
                {(playing) ? "Pause" : "Play"}
            </button>
        </div>
    )
}

Read this answer for more info.

Pradip Dhakal
  • 1,872
  • 1
  • 12
  • 29
0
import React, { useState } from "react";

//  Play icon
import voicemailplay from "../../assets/voicemail_play.png";
//  Pause icon
import voicemailpause from "../../assets/fax_call_icon.png";

//  Global declaration audio array
let audioArray = [];    

//  Global declaration audio array index
let audioIndex = '';

const VoicemailSider = (props) => {

    //  Manage flag
    const [isPlaying, setIsPlaying] = useState(false);

    //  Play audio
    const playAudio = (audioFilePath, index) => {
        
        if(audioIndex !== '' && audioArray[audioIndex]) {
            audioArray[audioIndex].pause();
        }

        setIsPlaying(
            index
        );

        audioArray = [];
        audioIndex = index;

        try{
            if(index !== '' && event !== '') {
                audioArray[index] = new Audio(audioFilePath);
                audioArray[index].play();
            }           
        } catch(error) {
            console.log("Could not paly this audio - ", error);
        }
        
    }

    //  Pause audio
    const pauseAudio = (index) => {
    
        setIsPlaying(
            false
        );
        
        audioArray[index].pause();      
    }
    
    return (
        <div>           
            <List           
                dataSource={voicemaillist}      //  Your data that comes from databse           
                renderItem={(item,index) => (                   
                    <List.Item key={index}>                     
                        <img src={isPlaying === index ? voicemailpause : voicemailplay } alt="voicemail_play" onClick={() => isPlaying !== index ? playAudio(item.audioFilePath, index) : pauseAudio(index) } id={"voicemail_play" + index} style={{width: 35 ,height: 35, margin: "0px 10px"}} />
                    </List.Item>                
                )}
            </List>
        </div>
    );
};

export default VoicemailSider;