所以我正在构建一个鼓垫类型的应用程序,除了这个,几乎所有的东西都在工作。
编辑:把整件事放在codesandbox上,如果有人想看一看:codesandbox.io/s/sleepy-darwin-jc9b5?file=/src/App.js
const [index, setIndex] = useState(0);
const [text, setText] = useState("");
const [theSound] = useSound(drumBank[index].url)
function playThis(num) {
setIndex(num)
}
useEffect(()=>{
if (index !== null) {
setText(drumBank[index].id);
theSound(index);
console.log(index)
}
}, [index])
当我按下一个按钮时,索引会更改为与该按钮关联的值,然后use效应钩子会从该索引处的数组中播放声音。但是,当我多次按下同一个按钮时,它只播放一次,因为当索引更改为相同值时,useState不会重新呈现应用。
我希望能够多次按下同一按钮,让应用程序重新渲染,因此每次按下按钮时都可以运行useEffect。有人能帮我怎么做吗?
这是我能从你的沙盒里找到的。
>
根据文档,每个useSound
只是一个声音,所以当试图通过React状态更新索引到声音库中使用时,播放的声音总是至少延迟一个渲染周期。我建议创建一个新的自定义钩子来封装你的9鼓声。
useDrumBank
使用drumbank数组并将9个鼓声实例化为一个数组。
const useDrumBank = (drumbank) => {
const [drum0] = useSound(drumbank[0].url);
const [drum1] = useSound(drumbank[1].url);
const [drum2] = useSound(drumbank[2].url);
const [drum3] = useSound(drumbank[3].url);
const [drum4] = useSound(drumbank[4].url);
const [drum5] = useSound(drumbank[5].url);
const [drum6] = useSound(drumbank[6].url);
const [drum7] = useSound(drumbank[7].url);
const [drum8] = useSound(drumbank[8].url);
return [drum0, drum1, drum2, drum3, drum4, drum5, drum6, drum7, drum8];
};
更新组件逻辑,将drumBank
数组传递给新的自定义挂钩。
const sounds = useDrumBank(drumBank);
以下是完整的代码:
function App() {
useEffect(() => {
document.addEventListener("keypress", key);
return () => document.removeEventListener("keypress", key);
}, []);
const [text, setText] = useState("");
const sounds = useDrumBank(drumBank);
function playThis(index) {
drumBank[index]?.id && setText(drumBank[index].id);
sounds[index]();
}
function key(e) {
const index = drumBank.findIndex((drum) => drum.keyTrigger === e.key);
index !== -1 && playThis(index);
}
return (
<div id="drum-machine" className="drumpad-container">
<div id="display" className="drumpad-display">
<p>{text}</p>
</div>
<button className="drum-pad" id="drum-pad-1" onClick={() => playThis(0)}>
Q
</button>
<button className="drum-pad" id="drum-pad-2" onClick={() => playThis(1)}>
W
</button>
<button className="drum-pad" id="drum-pad-3" onClick={() => playThis(2)}>
E
</button>
<button className="drum-pad" id="drum-pad-4" onClick={() => playThis(3)}>
A
</button>
<button className="drum-pad" id="drum-pad-5" onClick={() => playThis(4)}>
S
</button>
<button className="drum-pad" id="drum-pad-6" onClick={() => playThis(5)}>
D
</button>
<button className="drum-pad" id="drum-pad-7" onClick={() => playThis(6)}>
Z
</button>
<button className="drum-pad" id="drum-pad-8" onClick={() => playThis(7)}>
X
</button>
<button className="drum-pad" id="drum-pad-9" onClick={() => playThis(8)}>
C
</button>
</div>
);
}
加载后立即没有声音
为了用户的利益,浏览器不允许网站产生声音,直到用户与他们互动(例如。通过点击某些东西)。在用户点击、点击或触发某些东西之前,不会产生任何声音。
让按键持续工作似乎是一个问题,我没有立即想到一个解决方案,但至少在这一点上,按钮点击工作和声音同步播放。
您是否考虑过将这些离散状态变量(值类型)组合成单个引用类型状态对象?
当索引更改时,您只需同时设置整个状态,而不是设置文本的效果。
只要你确保这是一个新的对象/引用,那么效果就会触发。该效果然后只负责根据当前状态播放声音。
下面是一些示例代码
const [state, setState] = useState({ index: 0, text: '', });
const playThis = (num) => {
setState({ index: num, text: drumBank[num].id, });
};
useEffect(() => {
theSound(state.index);
}, [state]);
我有点像: 设置状态仍然是异步,那么等待这个调用完成的最佳方法是什么? 似乎不像那样接受回调。 在上面,我们希望按顺序运行每个setwhater调用。这是否意味着我们需要设置许多不同的useEffect挂钩来复制这种行为?
提前谢了。我有一个状态数组,如下所示。 我需要添加一个项目到状态数组,我发现我们不需要做状态突变。如何使用PrevState设置状态。 如何调用set State以追加此状态数组。 像这样的东西?
问题内容: tldr; 如何模拟或将prop与数组配合使用以强制重置组件? 我正在实现一个显示计时器的组件,并在该组件达到零时执行回调。目的是让回调更新对象列表。后一个组件由新的React钩子 和组成。 该包含在该定时器启动时的基准,而剩余的时间。该套间隔称为每秒钟更新的剩余时间,并检查是否回调应该叫。 该组件并不是要重新安排计时器的时间,或者在间隔达到零时保持间隔不变,而是应该执行回调和空闲。为
我想用React useState钩子设置多个状态值,这样我就可以用useEffect钩子分别更新它们。我有以下代码: 但是当我用React DevTools检查应用程序时,我会看到钩子的多个“状态”值,而不是“订单”、“支付”、“提交”等。
问题内容: 我正在尝试新的React Hooks,并有一个带有计数器的Clock组件,该计数器应该每秒增加一次。但是,该值不会增加到超过一。 问题答案: 原因是传递给的闭包中的回调仅访问第一个渲染器中的变量,而无法访问后续渲染器中的新值,因为第二次未调用。 回调中的值始终为0 。 就像您熟悉的状态挂钩一样,状态挂钩有两种形式:一种是处于更新状态的状态,另一种是将当前状态传入的回调形式。您应该使用第
我正在试用新的反应挂钩,并有一个时钟组件,计数器应该每秒钟增加一次。但是,该值不增加超过1。