【发布时间】:2021-05-05 13:40:45
【问题描述】:
我有一个组件,它从Tone.js 库(例如音频播放器和过滤器)中实例化一些类,并定义了一些作用于这些对象的函数,这些函数在一组 UI 呈现按钮中用作回调(参见相关代码如下)。
其中两个按钮应该使用useState hook(在updateSpatial 函数中)切换布尔状态is3D,以启用/禁用其中一个按钮。但是,此更新显然会导致组件完全重新渲染,从而重新实例化我的类,这会阻止定义的函数在之后工作。
相比之下,我也尝试了useRef hook,它允许is3D 更新而不重新渲染,但是按钮的禁用状态不会更新,因为组件不会重新渲染。
有适合这种情况的模式吗?我接下来的尝试包括使用 HOC、Context 或 Redux,但我不确定这是最直接的。谢谢!
import React, {useState, useEffect, Fragment} from 'react'
import { Player, Destination} from "tone";
const Eagles = () => {
const [is3D, setIs3D] = useState(false);
useEffect(() => {
// connect players to destination, ready to play
connectBase();
});
// Instantiating players
const player1= new Player({
"url": "https://myapp.s3.eu-west-3.amazonaws.com/Aguabeber.m4a",
"autostart": false,
"onload": console.log("player 1 ready")
});
const player2 = new Player({
"url": "https://myapp.s3.eu-west-3.amazonaws.com/Aguas.m4a",
"autostart": false,
"onload": console.log("player 2 ready")
});
// Functions
function connectBase() {
player1.disconnect();
player1.connect(Destination);
player2.disconnect();
player2.chain(Destination);
}
function playStudio() {
player1.volume.value = 0;
player2.volume.value = -60;
}
function playCinema() {
player1.volume.value = -60;
player2.volume.value = 0;
}
function playstereo() {
player1.volume.value = 0;
player2.volume.value = -60;
updateSpatial();
}
function playmyhifi() {
player1.volume.value = -60;
player2.volume.value = 0;
updateSpatial();
}
function start() {
player1.start();
player2.start();
playstereo();
}
function stop() {
player1.stop();
player2.stop();
console.log("stop pressed")
}
// Update state to toggle button enabled`
function updateSpatial() {
setIs3D((is3D) => !is3D);
}
return (
<Fragment>
<ButtonTL onClick={start}>Play</ButtonTL>
<ButtonTR onClick={stop}>Stop</ButtonTR>
<ButtonTL2 onClick={playstereo}>Stereo</ButtonTL2>
<ButtonTR2 onClick={playmyhifi}>3D</ButtonTR2>
<ButtonLL disabled={is3D} onClick={playStudio}>Studio</ButtonLL>
<ButtonLR onClick={playCinema}>Cinema</ButtonLR>
</Fragment>
)
}
【问题讨论】: