gpt4 book ai didi

reactjs - React useEffect 运行太频繁

转载 作者:行者123 更新时间:2023-12-04 14:47:35 26 4
gpt4 key购买 nike

简而言之:

我想在值更改时发生副作用,但前提是第二个值是 true。由于两个值都必须在依赖数组中,因此当第一个值未更改且第二个值“打开”时也会触发副作用,但我不希望它发生。

详细说明:

我正在用 React 创建游戏。我想在各种事件中播放(短)音效,例如输赢。我有一个简单的辅助函数来播放声音,它有效:

function playSound(url) {
new Audio(url).play();
}

所有游戏逻辑都在自定义 Hook useGame 中。除其他外,该 Hook 返回一个用户移动时的点击处理程序(它处理更新 Hook 中的所有相关状态)和一个 winner bool 值(指示游戏是否获胜) .

我无法在点击处理程序中调用 playSound,因为该闭包只能访问点击前的状态并且不知道点击后游戏是否获胜。所以我把它放在一个副作用中,用一个依赖数组来确保它只在游戏获胜时发生一次。

useEffect(() => {
if (winner) {
playSound(winSound);
}, [winner]);

[注意:在内部,winner 是无状态的;它是直接从(有状态的)董事会计算的。所以没有可以标记的 setWinner 调用。]

到这里一切正常。但现在我想添加一个用户设置以静音所有声音。

const [soundIsOn, setSoundIsOn] = useState(true);

现在我必须将其添加为调用 playSound 的条件(或将其作为参数传递给它)。

useEffect(() => {
if (winner && soundIsOn) {
playSound(winSound);
}, [winner, soundIsOn]);

请注意,依赖项数组现在需要包含 soundIsOn问题出现在声音关闭时,用户赢得游戏,然后用户稍后打开声音。由于 soundIsOn 更改,将调用此效果,从而产生获胜声音。

我通读了所有文档并查找了类似的问题。我见过的唯一可能的解决方案是 use a ref inside a custom hook跟踪以前的状态并检查哪个状态发生了变化,但这似乎有点困惑和不令人满意。有没有“正确”的方法来处理这类事情?理想情况下,要么通过修改效果,要么以某种方式将其应用到点击处理程序中。

最佳答案

解决方案 #1

用其他状态而不是获胜者对象本身来管理触发事件。

const [winner, _setWinner] = useState(...);
const [shouldPlaySound, setShouldPlaySound] = useState(false);
// wrapper function (it is not required)
const setWinner = (winner) => {
setShouldPlaySound(true);
_setWinner(winner)
}
...
// if winner is selected
setWinner(...);
...
// Side effect
useEffect(() => {
if(shouldPlaySound && soundIsOn){
playSound(winSound);
}
setShouldPlaySound(false);
}, [shouldPlaySound, soundIsOn])

另外,新的 setWinner 包装函数不需要用 useCallback 定义,因为它只包含 useState< 的 setState/.

但不需要定义 setWinner 包装器。这是代码可读性的选择。

解决方案 #2

但我认为如果你需要在选择获胜者时播放声音,只需在选择获胜者时调用 playSound 即可。

// when winner is selected
setWinner(winner);
if(soundIsOn){
playSound(winSound);
}

关于reactjs - React useEffect 运行太频繁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69732411/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com