![](/img/trans.png)
[英]State Value Stops Updating Within UseEffect Hook - Gatsby/React
[英]State variable inside a function defined within useEffect hook is not updating when value changes
我有一个项目需要测量 DOM 元素的高度,然后在 useState 挂钩中设置该值,最后在useState
挂钩中使用useEffect
值。 但是,我在useState
中定义的值(名为maxTranslate
)在 function 中使用。 即使我将maxTranslate
作为依赖项添加到useEffect
, maxTranslate
中的 maxTranslate 的值也不会从其初始值-440
改变。 我可以确认在useEffect
state 更改上触发了maxTranslate
。
我显然认为这与陈旧的闭包有关,但由于它正在重新渲染,我不太清楚为什么。 我错过了什么?
我首先定义一个useState
:
// state variable that defines a default maxTranslate value
const [maxTranslate, setMaxTranslate] = useState(-440)
这里我定义了一个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])
接下来,是我的useEffect
,它将maxTranslate
作为依赖项。 我可以在此处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]);
我的getStep
function 应该在页面重新渲染并关闭时重新定义 maxTranslate 的最新值的maxTranslate
,对吗? 这里发生了什么? 谢谢!
编辑:添加了完整的 useEffect
这里的问题是,由于 maxTranslate 值的变化,当 useEffect 再次运行时,您没有清理使用 createGesture 创建的先前侦听器
因此,当您不这样做时,即使组件不需要那些旧的侦听器,它们仍然会继续存在并且不会被垃圾收集,因为它们的引用不会丢失
因此,getStep 方法在为前一个侦听器触发时使用旧值调用
它始终建议您在清理 function 的 useEffect 时清除订阅和听众
useEffect(() => {
...
return () => {
swipeGesture.destroy();
}
}, [animationEl, maxTranslate])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.