简体   繁体   English

在 useEffect 挂钩中定义的 function 中的 State 变量在值更改时不会更新

[英]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作为依赖项添加到useEffectmaxTranslate中的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM