![](/img/trans.png)
[英]React: How to show Spinner & Component (at the same time) when State Changes using `useEffect`
[英]React hooks - how to force useEffect to run when state changes to the same value?
所以我正在构建一个鼓垫类型的应用程序,几乎所有东西都在工作,除了这个。
编辑:如果有人想看的话,把整个东西放在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])
当我按下按钮时,索引更改为与按钮关联的值,然后 useEffect 挂钩从该索引处的数组播放声音。 但是,当我多次按下同一个按钮时,它只会播放一次,因为当索引更改为相同的值时,useState 不会重新渲染应用程序。
我希望能够多次按下同一个按钮并让应用程序重新渲染,因此每次按下按钮时都会运行 useEffect。 谁能帮助我如何做到这一点?
您是否考虑过将这些离散的 state 变量(值类型)组合成单个引用类型 state object?
而不是在索引更改时设置文本的效果,您只需同时设置整个 state。
只要您确保这是一个新的对象/引用,那么效果就会触发。 然后效果器只负责播放基于当前 state 的声音。
这是我可以从您的沙盒中得出的结论。
根据文档,每个useSound
只是一个声音,因此当尝试将索引更新到音库以通过 React state 使用时,播放的声音将始终延迟至少一个渲染周期。 我建议创建一个新的自定义挂钩来封装您的 9 鼓声音。
useDrumBank
使用鼓组数组并将 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>
);
}
为用户着想,浏览器不允许网站在用户与它们进行交互(例如,通过点击某物)之前产生声音。 在用户点击、轻敲或触发某些东西之前,不会产生声音。
让按键持续工作似乎是一个问题,我没有立即想到解决方案,但至少此时按钮点击工作并且声音同步播放。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.