[英]Why can't I update the state of my component from within a useEffect callback?
I am trying to create a timer that is started once the app is in the background, and then when the app is called to the foreground again the app checks if it has been 15 minutes (for ease of testing I am using 15s currently).我正在尝试创建一个计时器,该计时器在应用程序处于后台时启动,然后当应用程序再次被调用到前台时,应用程序会检查它是否已经过了 15 分钟(为了便于测试,我目前使用的是 15 秒)。 If it has the app logs the user out, else the timer resets.
如果它让应用程序将用户注销,则计时器会重置。
If this is a dupe please refer me - I just couldn't find anything.如果这是一个骗局,请转介我 - 我找不到任何东西。 I've been trying to work this out for a couple of days now.
这几天我一直在努力解决这个问题。
Here is my thinking:这是我的想法:
Here is my problem:这是我的问题:
Things to note:注意事项:
const rootNavigator = () => {
const dispatch = useDispatch()
const [loginTimer, setLoginTimer] = useState(Date.now())
useEffect(() => {
AppState.addEventListener('change', handleAppStateChange)
return (() => {
AppState.removeEventListener('change', handleAppStateChange)
})
}, [])
const handleAppStateChange = (state) => {
if (state === "inactive" || state === "background") {
setLoginTimer(Date.now())
}
if (state === "active") {
if (Date.now() - loginTimer < 15000) {
setLoginTimer(Date.now())
} else if (Date.now() - loginTimer >= 15000) {
dispatch(logout())
}
}
}
return (
<SomeComponent />
...
)
}
I am almost certain this is a pretty basic error I am running into because my understanding of how this is meant to be handled is not yet well formed enough.我几乎可以肯定这是我遇到的一个非常基本的错误,因为我对如何处理它的理解还不够完善。
Thanks in advance.提前致谢。
The problem is coming from your reference to useState
data in the callback function handleAppStateChange()
.问题来自您在回调 function
handleAppStateChange()
中对useState
数据的引用。 The callback for AppState.addEventListener
is registered when the component mounts, but a snapshot of the current state is used for that callback each time it is called, and therefore, it will not be reactive in the way you would like. AppState.addEventListener
的回调在组件挂载时注册,但当前 state 的快照在每次调用时用于该回调,因此,它不会以您想要的方式响应。
The good news is that there are a number of ways to fix this issue, and some of those are explained in nice detail in this great answer here .好消息是有很多方法可以解决这个问题,其中一些在这个很好的答案中得到了很好的详细解释。
My solution, using information from Jacob K's link.我的解决方案,使用来自 Jacob K 链接的信息。 It was very simple in the end and I got it down to an even more succinct statement.
最后它非常简单,我把它归结为一个更简洁的陈述。 Can probably use a ternary, but this works just fine.
可能可以使用三元,但这很好用。
const rootNavigator = () => {
const dispatch = useDispatch()
const timer = useRef(Date.now())
useEffect(() => {
AppState.addEventListener('change', handleAppStateChange)
return (() => {
AppState.removeEventListener('change', handleAppStateChange)
})
}, [])
const handleAppStateChange = (state) => {
if (state === "inactive" || state === "background") {
timer.current = Date.now()
}
if (state === "active" && (Date.now() - timer.current > 15000)) {
dispatch(logout())
}
}
return (
<SomeComponent />
...
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.