我不明白为什么我的useEffect()
React函数无法访问组件的状态变量。当用户放弃在我们的应用中创建列表并导航到另一个页面时,我正在尝试创建日志。我正在使用useEffect()
return
方法来复制componentWillUnmount()
生命周期方法。你能帮忙吗?
let[progress, setProgress] = React.useState(0)
... user starts building their listing, causing progress to increment ...
console.log(`progress outside useEffect: ${progress}
useEffect(() => {
return () => logAbandonListing()
}, [])
const logAbandonListing = () => {
console.log(`progress inside: ${progress}`)
if (progress > 0) {
addToLog(userId)
}
}
代码将到达addToLog()
,从而导致记录此行为。
当用户在列表中输入内容,导致progress
递增,然后离开页面时,就会发生这种情况。
useEffect()
方法工作完美,并触发了logAbandonListing()
函数console.log()
状态,第一个useEffect
(在progress
上方)记录的值大于0 console.log()
将progress
状态记录为0,从而使代码无法返回true
语句的if
并到达addToLog()
函数。 / li>
我非常感谢您的帮助,以帮助您了解这里的情况。谢谢。
答案 0 :(得分:6)
我认为这是一个典型的过时关闭问题。一开始很难理解。
使用空的依赖项数组,useEffect将仅运行一次。并且它将从那一次运行中访问状态。因此,此刻它将从logAbandonListing函数获得引用。此功能还将从此刻开始访问状态。您可以通过多种方式解决问题。
其中之一是将状态变量添加到您的依赖项中。
useEffect(() => {
return () => logAbandonListing()
}, [progress])
另一种解决方案是将状态值设置为ref。而且ref的引用没有改变,因此您将始终看到最新鲜的值。
let[progress, setProgress] = React.useState(0);
const progressRef = React.createRef();
progressRef.current = progress;
...
const logAbandonListing = () => {
console.log(`progress inside: ${progressRef.current}`)
if (progressRef.current > 0) {
addToLog(userId)
}
}
如果userId也发生变化,则应将其添加到依赖项或引用中。
答案 1 :(得分:2)
要在useEffect
依赖项是空数组useEffects
的{{1}}返回函数中使用状态的当前值进行操作,可以使用[]
。这样,您可以避免过时的关闭问题,并可以通过useReducer
的{{1}}函数来更新状态。
示例为:
useReducer
有关此answer
的更多信息答案 2 :(得分:0)
当您从useEffect
返回一个函数时,它的行为类似于componentWillUnmount
,所以我认为它仅在清理时运行。您实际上需要像这样呼叫logAbandonListing
:
useEffect(() => {
logAbandonListing();
}, []);
因此它在每次重新渲染组件时运行。您可以在https://reactjs.org/docs/hooks-effect.html
上了解有关useEffect
的更多信息
写得很好。
答案 3 :(得分:0)
我尝试使用此沙箱来解释我的答案。 enter link description here
基本上,您是从useEffect回调返回一个函数。但是从未真正调用过该返回的函数,因此它实际上并未执行,因此记录了放弃操作。如果您查看沙盒中的代码,则之后我添加了包装器Parens和(),以实际上导致方法的调用导致console.log的执行。