I'm trying to create a basic audio player and keeping track of the player state using the state hook.
The following code creates a component with the following behaviour:
import React, {useState} from 'react'
function InlinePlayer ({audio}) {
const [playing, setPlaying] = useState(false)
const player = new Audio(audio.asset.url)
function togglePlay () {
playing ? player.pause() : player.play()
setPlaying(!playing)
}
return <>
<button onClick={() => togglePlay()}>
{playing ? 'Stop' : 'Play' }
</button>
</>
}
export default InlinePlayer
If I don't use the state hook at all I can stop and start the audio without issues.
One strange thing is that even if I call play() unconditionally and then call the state hook, subsequent calls to pause() also don't work anymore. It's as if calling setPlaying() destroys the connection to the player object. If I comment out the setPlaying line, it works.
function play () {
player.play()
setPlaying(true)
}
function pause () {
player.pause()
setPlaying(false)
}
I initially thought the problem was that the state was being set asynchronously so the conditional play was the culprit. What seems to be up here?
player.pause()
and player.play()
are like side effects. Use useEffect
with proper cleanup function so you can toggle the play/pause
:
import React, { useState, useEffect } from "react";
function InlinePlayer({ audio }) {
const [playing, setPlaying] = useState(false);
const player = new Audio(
"https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
);
useEffect(() => {
playing ? player.play() : player.pause();
// This is cleanup of the effect
return () => player.pause();
}, [playing]);
// ^ Run the effect every time the `playing` is changed
function togglePlay() {
// Using the callback version of `setState` so you always
// toggle based on the latest state
setPlaying(s => !s);
}
return (
<>
<button onClick={() => togglePlay()}>{playing ? "Stop" : "Play"}</button>
</>
);
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加