#reactjs #react-hooks
#reactjs #реагирование-перехваты
Вопрос:
Я пытаюсь создать базовый аудиоплеер и отслеживать состояние проигрывателя с помощью перехвата состояния.
Следующий код создает компонент со следующим поведением:
- При первом нажатии кнопки воспроизводится звук
- При каждом нажатии кнопки текст переключается правильно
- Когда состояние воспроизводится, вызов player.pause() ничего не делает
- Когда состояние не воспроизводится, звук продолжается, и вызов player.play() приводит к запуску второго уровня звука сверху
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
Если я вообще не использую перехват состояния, я могу остановить и запустить звук без проблем.
Одна странная вещь заключается в том, что даже если я вызываю play() безоговорочно, а затем вызываю перехват состояния, последующие вызовы pause() также больше не работают. Это как если бы вызов setPlaying() разрушал соединение с объектом player. Если я закомментирую строку setPlaying, это сработает.
function play () {
player.play()
setPlaying(true)
}
function pause () {
player.pause()
setPlaying(false)
}
Сначала я думал, что проблема заключалась в том, что состояние устанавливалось асинхронно, поэтому виновником было условное воспроизведение. Что, кажется, здесь?
Ответ №1:
player.pause()
и player.play()
похожи на побочные эффекты. Используйте useEffect
с правильной функцией очистки, чтобы вы могли переключать 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>
</>
);
}
Комментарии:
1. Замечательно, у меня было ощущение, что я должен использовать useEffect, но не мог понять, как. Спасибо!