javascript - 当侦听器回调更新状态时,React useState(prevState => ...) 不起作用
问题描述
介绍
我的屏幕上有一个进度时间栏,它在 setInterval 内的 useEffect 中高级。当我的数据库侦听器被触发并执行其回调时,问题就出现了,代码更新其他状态。
代码
const [isRoomFull, setIsRoomFull] = useState(false);
const [timerProgress, setTimerProgress] = useState(0);
...
const startGame = () => {
...
advanceTimer();
}
const listenRoomChanges = (roomDoc) => {
const { full } = roomDoc.data();
setIsRoomFull(full);
};
const advanceTimer = () => {
setTimerProgress(timerProgress + 1 / GAME_DURATION);
};
useEffect(() => {
if (roomId) {
const { firebase } = props;
roomListener.current = firebase
.getDatabase()
.collection("rooms")
.doc(roomId)
.onSnapshot(listenRoomChanges); // <- DB listener callback
}
return () => {
detachListener();
};
}, [roomId]);
useEffect(() => {
if (timerProgress > 0 && timerProgress < 1) {
// Advance the timer every second
var timerInterval = setInterval(() => {
advanceTimer();
}, 1000);
}
return () => {
clearInterval(timerInterval);
};
}, [timerProgress]);
问题
问题是每次执行侦听器回调时都会重置 timerProgress 值。
例如,如果我在侦听器回调中执行 console.log(timerProgress)
const listenRoomChanges = (roomDoc) => {
const { full } = roomDoc.data();
console.log(timerProgress); // <----
setIsRoomFull(full);
};
例如,当实际值为 10 秒时,它将显示 0。
我目前的解决方法
如果在更新计时器进度时我会
const advanceTimer = () => {
setTimerProgress(
(prevTimerProgress) => prevTimerProgress + 1 / GAME_DURATION
);
};
相反,当 DB 侦听器回调更新其他状态时, timerProgress 不会“重置”为 0...
但是由于某种原因,这不能 100% 正常工作(当 DB 侦听器回调更新其他状态时,timerProgress 提前nStateUpdatesInTheDbListenerCallback时间更快,我不知道原因,但这种情况正在发生)。
有人知道如何解决这个问题吗?有什么特殊的钩子吗?为什么会这样?
我认为我可以使用 useRef() 但这不会触发重新渲染...
谢谢你。
解决方案
消除 return () => { clearInterval(time interval);};
从
useEffect(() => {
if (timerProgress > 0 && timerProgress < 1) {
// Advance the timer every second
var timerInterval = setInterval(() => {
advanceTimer();
}, 1000);
}
return () => {
clearInterval(timerInterval);
};
}, [timerProgress]);
让我知道,
推荐阅读
- python - 如何使用 Selenium 和 Python 从 GoogleForm 非选择下拉列表中选择一个选项
- javascript - Vue.js如何将索引添加到模态窗口
- c++ - 在 Windows 中限制帧率
- macos - 修复文件访问权限
- html - 如何通过使用 CSS 将形状组合成一个来创建云?
- javascript - 单击时隐藏/显示部分表单。如何调试?
- ruby-on-rails - 如何通过从其他表中查找 id 来应用范围
- python - 以编程方式设置python路径
- javascript - 通过 Js 检索共享点列表
- javascript - 在这种情况下,你能在循环中返回一个布尔值吗