Ian
Ian

Reputation: 41

Volume slider is playing audio files correctly onClick but not changing the volume of key presses for the same element

Basically if I change the slider level it only affects the click and not also the keydown, even though they call the same playSound Function. Not sure what I have messed up

function App() {
  const [soundText, setSoundText] = useState();
  const [volumeLevel, setVolumeLevel] = useState(0.5)
};

I have it split by component, I had to cut out most of the App component to post, but you get the point

function DrumPad({ pad, setSoundText, volumeLevel }) {
    
    useEffect(() => {
        document.addEventListener('keydown', handleKeyPress);
        return () => {
            document.removeEventListener('keydown', handleKeyPress)
        };
    }, []);

    const playSound = () => {
        const audioTag = document.getElementById(pad.letter);
        audioTag.volume = volumeLevel;
        audioTag.play();
        setSoundText(pad.id)
    }
    const handleKeyPress = (e) => {
        if(e.keyCode === pad.keyCode){
            playSound();
        }
    }
    

    return (
        <div 
        className="drum-pad" 
        id={pad.id}
        onClick={playSound}>
            <p>{pad.letter}</p>
            <audio 
                src={pad.src} 
                className="clip" 
                id={pad.letter}>
            </audio>
        </div>
    )
}
function VolumeBar({ setSoundText, volumeLevel, setVolumeLevel }) {
    const volumeChanger = (e) => {
        setVolumeLevel(e.target.value)
    }
    return (
        <div className="slide-container">
            Volume
            <input 
                id="myRange"
                type="range"
                min='0'
                max='1'
                step= '0.01'
                value={ volumeLevel }
                onChange={ volumeChanger }
                className="slider"
            />
        </div>
    )
}

Thank you

Upvotes: 3

Views: 108

Answers (2)

rreskey
rreskey

Reputation: 45

.useEffect should depend on a pad. So it runs useEffect everytime pad changes (either keypress or onClick event) This should work:

function DrumPad({ pad, setSoundText, volumeLevel }) {
    
    useEffect(() => {
        document.addEventListener('keydown', handleKeyPress);
        return () => {
            document.removeEventListener('keydown', handleKeyPress)
        };
    }, [pad]); // add *pad* here instead of having empty []

Upvotes: 2

Al&#236; Shadman
Al&#236; Shadman

Reputation: 242

Instead of using event listener, which are not encouraged in react, try to add onKeyDown props to the input.

  <input 
            id="myRange"
            type="range"
            min='0'
            max='1'
            step= '0.01'
            value={ volumeLevel }
            onChange={ volumeChanger }
            onKeyDown={(e) => {
               if(e.keyCode === pad.keyCode){
                 playSound();
               }}}
            className="slider"
        />

Upvotes: 1

Related Questions