简体   繁体   中英

play / pause button not working properly // React // wavesurfer.js

I have been struggling for HOURS trying to beat this, but i can´t do it.

The problem down below have a BUTTON, which has a child of an FontAwesomeIcon component. i want the icon to change, is audio playing? then display the pause icon, if not.. you get the rest.

However, when i click the play button, it changes the icon as expected, and the audio plays. when i click it again, this is when the problem occurs. It will not pause the music, and it will certainly not change the icon back.

Can someone help me figure this out?

    import React from 'react';
import { useState, useRef, useEffect } from 'react';
import wavesurfer from 'wavesurfer.js';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import { faCirclePlay, faCirclePause } from "@fortawesome/free-solid-svg-icons";





const AudioVisualizer = (props) => {
    const audioRef = useRef(null);
    // const [playing, setPlay] = useState(null);
    const [isClicked, setIsClicked] = useState(false)
    const [volume, setVolume] = useState(0.5);

    const [isBtnClicked, setBtnClicked] = useState(false)
    const [icon, setIcon] = useState(faCirclePlay);




    let audioTrack;

    useEffect(()=>{
        if (audioRef.current){
                audioTrack = wavesurfer.create({
                container: audioRef.current,
                progressColor: "#13AEA2",
                waveColor: "#eeee",
                cursorColor: "OrangeRed",
                preload: true,
                backend: "MediaElement",
                barWidth: 2,
                barHeight: 1, // the height of the wave
                fillParent: true,
                hideScrollbar: true,
                responsive: true,
                
            });
            audioTrack.load(props.audio);

        

            // audioTrack.load(props.audio);
        }
    }, [])   
    





    const onVolumeChange = e => {
        const { target } = e;
        const newVolume = +target.value;
        
    
        if (newVolume) {
            console.log("new volume true,,, volume: " + volume)
            setVolume(volume => newVolume);
            audioTrack.current.setVolume(newVolume || 1);
        }
    };



    const clicking =  (e) => {
        // Get a view of what the "click" registers:
        console.log(e.currentTarget.tagName);
        console.log(e.target);
        
        // if plying == pause
        if ( ! audioTrack.isPlaying() ) {
            console.log("not playing.. Start playing");
            audioTrack.play()
            setIcon(icon => faCirclePause)
            return

        } 


        console.log("Is playing.. will pause")
        audioTrack.play()
        setIcon(faCirclePlay);
        
        return
        
    
    };
    // FontAwesomeIcon => onClick change icon + pause/play audio. 
    
    return (
        <>
            <div  className='audio'  ref={audioRef}>
            </div> 
            <div className='audioKnobs'>
                
                <button  className='playpausewrapper' onClick={clicking}>
                        <FontAwesomeIcon className='playButton' icon={icon} />
                </button>

                <input type="range" id="volume" name="volume" min="0.01" max="1" step=".025" onChange={onVolumeChange} defaultValue={volume}/>
            </div>
        </>
    )
}


export default AudioVisualizer;

Error from console: Img 显示了一些代码和本地主机预览和控制台..

AudioVisualizer.js:75 Uncaught TypeError: Cannot read properties of undefined (reading 'isPlaying')
    at clicking (AudioVisualizer.js:75:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
    at invokeGuardedCallback (react-dom.development.js:4277:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1)
    at executeDispatch (react-dom.development.js:9041:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1)
    at processDispatchQueue (react-dom.development.js:9086:1)
    at dispatchEventsForPlugins (react-dom.development.js:9097:1)
    at react-dom.development.js:9288:1

Everything inside of a component is run every render. Components can rerender thousand of times.

You are declaring a variable every render:

let audioTrack;

But you are assigning the value only once

useEffect(()=>{
        if (audioRef.current){
                audioTrack = wavesurfer.create({
                container: audioRef.current,
                progressColor: "#13AEA2",
                waveColor: "#eeee",
                cursorColor: "OrangeRed",
                preload: true,
                backend: "MediaElement",
                barWidth: 2,
                barHeight: 1, // the height of the wave
                fillParent: true,
                hideScrollbar: true,
                responsive: true,
                
            });
            audioTrack.load(props.audio);

        

            // audioTrack.load(props.audio);
        }
    }, [])

You can't use normal variables like that.

You have to use ref

At the beginning of the component:

const audioTrackRef = useRef(undefined);

In the useEffect

audioTrackRef.current = wavesurfer.create({
                container: audioRef.current,
                progressColor: "#13AEA2",
                waveColor: "#eeee",
                cursorColor: "OrangeRed",
                preload: true,
                backend: "MediaElement",
                barWidth: 2,
                barHeight: 1, // the height of the wave
                fillParent: true,
                hideScrollbar: true,
                responsive: true,
                
            });

And in every other place

audioTrackRef.current

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM