如果使用 useState React Tonejs 则无法停止播放器
Cannot stop player if use useState React Tonejs
我正在尝试使用 tonejs 库在我的 React 项目中实现一个 start/stop 按钮,但是在我使用 setState 更改我的图标后,我的 player.stop() 功能不起作用.如果我再按 2 次按钮,第二个播放器会发出声音。
这是我的代码
const [play, setPlay] = useState(false);
const buffer = new Tone.Buffer("audio.mp3");
const player = new Tone.Player(buffer).toDestination();
const startMusic = () => {
if (buffer.loaded) {
player.start();
setPlay(true);
}
}
const muteMusic = () => {
player.stop();
console.log(player.buffer)
setPlay(false);
}
<Avatar className="hover" style={{ position: 'absolute', top: '10px', left: '10px' }}>
{play == true ? <VolumeUpRounded onClick={() => { muteMusic() }} /> : <VolumeOff onClick={() => { startMusic() }} />}
</Avatar>
更新:
现在我使用 ContextProvider 来只控制音频,我调用儿童
中的函数
import { createContext } from "react";
import * as Tone from "tone";
import chopin from "../assets/songs/audio.mp3"
const AudioContext = createContext({
start: null,
stop: null,
})
export default AudioContext;
export const AudioContextProvider = (props) => {
const buffer = new Tone.Buffer(chopin);
const player = new Tone.Player(buffer).toDestination();
const start = () => {
player.start();
console.log('started!');
}
const stop = () => {
player.stop();
console.log('stopped');
}
return (
<AudioContext.Provider value={{
start: start,
stop: stop,
}}>
{props.children}
</AudioContext.Provider>
)
}
并像这样使用:
import AudioController from "../context/audio-context-controller";
const audioController = React.useContext(AudioController);
const [started, setStarted] = useState(false);
const start = () => {
audioController.start();
setStarted(true);
}
const stop = () => {
audioController.stop();
setStarted(false);
}
如上所述,setState 方法生成的渲染始终允许您拥有一个新的播放器实例,突然间您无法访问该对象的当前状态。
背后的想法是在组件外部有一个实例,即使组件是 re-rendered,你也将始终拥有相同的 Player 实例。
const player = new Tone.Player("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3").toDestination();
function Example() {
const [play, setPlay] = useState(false);
const startMusic = () => {
player.start();
setPlay(true);
}
const muteMusic = () => {
player.stop();
setPlay(false);
}
return (
<div>
<button onClick={play===true ? muteMusic : startMusic}>
{play ===true ? "stop" : "start"}
</button>
</div>
);
}
考虑创建一个服务,这样您将始终在应用程序上获得一个单例。
我正在尝试使用 tonejs 库在我的 React 项目中实现一个 start/stop 按钮,但是在我使用 setState 更改我的图标后,我的 player.stop() 功能不起作用.如果我再按 2 次按钮,第二个播放器会发出声音。
这是我的代码
const [play, setPlay] = useState(false);
const buffer = new Tone.Buffer("audio.mp3");
const player = new Tone.Player(buffer).toDestination();
const startMusic = () => {
if (buffer.loaded) {
player.start();
setPlay(true);
}
}
const muteMusic = () => {
player.stop();
console.log(player.buffer)
setPlay(false);
}
<Avatar className="hover" style={{ position: 'absolute', top: '10px', left: '10px' }}>
{play == true ? <VolumeUpRounded onClick={() => { muteMusic() }} /> : <VolumeOff onClick={() => { startMusic() }} />}
</Avatar>
更新: 现在我使用 ContextProvider 来只控制音频,我调用儿童
中的函数import { createContext } from "react";
import * as Tone from "tone";
import chopin from "../assets/songs/audio.mp3"
const AudioContext = createContext({
start: null,
stop: null,
})
export default AudioContext;
export const AudioContextProvider = (props) => {
const buffer = new Tone.Buffer(chopin);
const player = new Tone.Player(buffer).toDestination();
const start = () => {
player.start();
console.log('started!');
}
const stop = () => {
player.stop();
console.log('stopped');
}
return (
<AudioContext.Provider value={{
start: start,
stop: stop,
}}>
{props.children}
</AudioContext.Provider>
)
}
并像这样使用:
import AudioController from "../context/audio-context-controller";
const audioController = React.useContext(AudioController);
const [started, setStarted] = useState(false);
const start = () => {
audioController.start();
setStarted(true);
}
const stop = () => {
audioController.stop();
setStarted(false);
}
如上所述,setState 方法生成的渲染始终允许您拥有一个新的播放器实例,突然间您无法访问该对象的当前状态。
背后的想法是在组件外部有一个实例,即使组件是 re-rendered,你也将始终拥有相同的 Player 实例。
const player = new Tone.Player("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3").toDestination();
function Example() {
const [play, setPlay] = useState(false);
const startMusic = () => {
player.start();
setPlay(true);
}
const muteMusic = () => {
player.stop();
setPlay(false);
}
return (
<div>
<button onClick={play===true ? muteMusic : startMusic}>
{play ===true ? "stop" : "start"}
</button>
</div>
);
}
考虑创建一个服务,这样您将始终在应用程序上获得一个单例。