[英]State variable inside a function defined within useEffect hook is not updating when value changes
I have a project where I need to measure the height of DOM elements, then set that value in a useState
hook and finally use the state value in a useEffect
hook.我有一个项目需要测量 DOM 元素的高度,然后在 useState 挂钩中设置该值,最后在
useState
挂钩中使用useEffect
值。 However, the value that I define in useState
(named maxTranslate
) is used within a function.但是,我在
useState
中定义的值(名为maxTranslate
)在 function 中使用。 Even though I add maxTranslate
as a dependency to useEffect
, the value of maxTranslate
inside the function does not change from its initial value of -440
.即使我将
maxTranslate
作为依赖项添加到useEffect
, maxTranslate
中的 maxTranslate 的值也不会从其初始值-440
改变。 I can confirm that the useEffect
is being triggered on maxTranslate
state change though.我可以确认在
useEffect
state 更改上触发了maxTranslate
。
I obviously think this has to do with stale closures but since it is re-rendering, I'm not quite sure why.我显然认为这与陈旧的闭包有关,但由于它正在重新渲染,我不太清楚为什么。 What am I missing?
我错过了什么?
I first define a useState
:我首先定义一个
useState
:
// state variable that defines a default maxTranslate value
const [maxTranslate, setMaxTranslate] = useState(-440)
Here I define a useEffect
that takes in 3 DOM refs and calculates their getBoundingClientRect().height
这里我定义了一个
useEffect
接受 3 个 DOM refs 并计算它们的getBoundingClientRect().height
// useEffect to calculate the height of 3 DOM elements
// please let me know if there there's a better semantic way of doing something like this
useEffect(() => {
setMaxTranslate((-1 * ((pageSize?.height || 0) - (previewSize?.height || 0) - (headerSize?.height || 0))))
}, [pageSize, previewSize, headerSize])
Next, is my useEffect
that takes in maxTranslate
as a dependency.接下来,是我的
useEffect
,它将maxTranslate
作为依赖项。 I can console.log
the maxTranslate
in here and confirm that the value updates properly.我可以在此处
console.log
maxTranslate
并确认该值正确更新。
// when maxTranslate changes from the useEffect above, the useEffect below will fire again
useEffect(() => {
let started: boolean = false;
let initialStep: number = 0;
const square = Array.from(animationEl.current!.nodes.values())[0];
const swipeGesture = createGesture({
el: square,
gestureName: 'swipeGesture',
direction: 'y',
threshold: 0,
onMove: (ev) => onMove(ev),
onEnd: (ev) => onEnd(ev),
});
swipeGesture.enable(true);
const onMove = (ev: GestureDetail) => {
if (!started) {
setProgressStart({ forceLinearEasing: true });
started = true;
}
setProgressStep({ step: getStep(ev) });
};
const onEnd = (ev: GestureDetail) => {
if (!started) {
return;
}
swipeGesture.enable(false);
const step = getStep(ev);
const shouldComplete = step > 0.25;
setProgressEnd({ playTo: shouldComplete ? 1 : 0, step });
setOnFinish({
callback: () => {
swipeGesture!.enable(true);
setProgressStart(undefined);
setProgressStep(undefined);
setProgressEnd(undefined);
},
opts: { oneTimeCallback: true },
});
initialStep = shouldComplete ? maxTranslate : 0;
started = false;
};
const getStep = (ev: GestureDetail) => {
const delta = initialStep + ev.deltaY;
// THIS VALUE OF maxTranslate DOES NOT CHANGE FROM THE INITIAL VALUE OF -440 THOUGH!
return clamp(0, delta / maxTranslate, 1);
};
}, [animationEl, maxTranslate]);
My getStep
function should be getting redefined once the page re-renders and closes over the scope of the most recent value of maxTranslate
, correct?我的
getStep
function 应该在页面重新渲染并关闭时重新定义 maxTranslate 的最新值的maxTranslate
,对吗? What's going on here?这里发生了什么? Thanks!
谢谢!
EDIT: added full useEffect编辑:添加了完整的 useEffect
The issue here is that you aren't cleaning up the previous listeners created with createGesture when the useEffect runs again due to change in maxTranslate value这里的问题是,由于 maxTranslate 值的变化,当 useEffect 再次运行时,您没有清理使用 createGesture 创建的先前侦听器
So when you don't do that, even though the component isn't needing those old listeners they still do continue to exist and are not garbage collected since their reference in not lost因此,当您不这样做时,即使组件不需要那些旧的侦听器,它们仍然会继续存在并且不会被垃圾收集,因为它们的引用不会丢失
Hence the getStep method was called with old value as it fired for the previous listener因此,getStep 方法在为前一个侦听器触发时使用旧值调用
Its always advices that you clear your subscriptions and listeners in cleanup function of useEffect它始终建议您在清理 function 的 useEffect 时清除订阅和听众
useEffect(() => {
...
return () => {
swipeGesture.destroy();
}
}, [animationEl, maxTranslate])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.