【发布时间】:2021-02-26 06:22:52
【问题描述】:
简介
我的屏幕上有一个进度时间栏,它在 setInterval 内的 useEffect 中高级。当我的 DB 侦听器被触发并执行其回调时,问题就出现了,代码会更新其他状态。
代码
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() 但这不会触发重新渲染...
谢谢。
【问题讨论】:
标签: javascript reactjs react-native