我试图使元素的位置:"固定"后,它滚动到屏幕的末尾,每当它回到第一个屏幕时,它应该再次获得的位置为"相对",但当它滚动到屏幕的末尾时,状态更改为真(已修复),但当它回滚时,它不会更改为假(相对).

const [fixed, setFixed] = useState(() => {
    return false;
  });
const scrollHandler = () => {
    if (window.scrollY > window.innerHeight) {

      if (!fixed) {
       
        setFixed(true);
      }
    } else {
      if (fixed) {
        setFixed(false);
      }
    }
  };
  useEffect(() => {
    window.addEventListener("scroll", scrollHandler);

    return () => {
      window.removeEventListener("scroll", scrollHandler);
    };
  }, []);

return (
    <>
      <div
        style={{ position: `${fixed ? "fixed" : "relative"}` }}
        className={classes.navigationBelt}
      ></div>
 </> );

以下是代码说明 我取了一个名为"FIXED"的状态,初始值为"FALSE"

const [fixed, setFixed] = useState(() => {
    return false;
  });

当组件安装到DOM中时,我已经在滚动窗口上添加了一个EventListener.

 useEffect(() => {
    window.addEventListener("scroll", scrollHandler);

    return () => {
      window.removeEventListener("scroll", scrollHandler);
    };
  }, []);

为了处理scroll事件,我创建了一个名为"scllHandler"的函数

const scrollHandler = () => {
    if (window.scrollY > window.innerHeight) {

      if (!fixed) {
       
        setFixed(true);
      }
    } else {
      if (fixed) {
        setFixed(false);
      }
    }
  };

当滚动超过窗口高度时,我将"FIXED"设置为"TRUE",并将一个元素设置为"FIXED".注意:我只在"FIXED"状态为FALSE时才更新状态,否则会导致多次重新渲染.

return (
    <>
      <div
        style={{ position: `${fixed ? "fixed" : "relative"}` }}
        className={classes.navigationBelt}
      ></div>
 </> );

它工作得很好,但是当它回滚时,当"Else"条件仍然命中时,状态("FIXED")显示为FALSE,即使它已经改变并且元素已经被修复.因此,setFixed(FALSE)不起作用,因为外部条件仍然为FALSE.

else {
      if (fixed) {
        setFixed(false);
      }
    }

我想知道为什么会发生这种事?

推荐答案

因为当fixed变量为false(the initial state)时,您附加到窗口的scrollHandler可以访问该变量.

您将其附加到只运行一次useEffect中,因此它将始终保留scrollHandler的引用.

您可以将fixed作为依赖项传递给useEffect,这样它将刷新/更新事件处理程序.

  useEffect(() => {
    window.addEventListener("scroll", scrollHandler);

    return () => {
      window.removeEventListener("scroll", scrollHandler);
    };
  }, [fixed]);

上面的解决方案有一个"问题",即您需要知道scrollHandler做了什么才能指定/更新useEffect的依赖项列表.

更明智的方法是在scrollHandler发生变化时重新运行useEffect,因为它是在useEffect(and this is the real dependency of that 100)中使用的.

  useEffect(() => {
    window.addEventListener("scroll", scrollHandler);

    return () => {
      window.removeEventListener("scroll", scrollHandler);
    };
  }, [scrollHandler]);

但是,由于您的代码将在组件的每次重新呈现中更改scrollHandler处理程序,因此您应该try 使其尽可能"稳定",即在函数本身的依赖项相同的情况下保留/重用该函数的相同引用.为此,您可以使用useCallback,并使用fixed作为其依赖项.

const scrollHandler = useCallback(() => {
  if (window.scrollY > window.innerHeight) {

    if (!fixed) {
      setFixed(true);
    }
  } else {
    if (fixed) {
      setFixed(false);
    }
  }
}, [fixed]);

Javascript相关问答推荐

在JavaScript中使用setProperty方法试图修改css元素值时,我遇到错误

Angular:ng-contract未显示

如何为GrapesJS模板编辑器创建自定义撤销/重复按钮?

Vega中的模运算符

Klaro与Angular的集成

如何解决CORS政策的问题

按下同意按钮与 puppeteer 师

如何在Javascript中的控制台上以一行形式打印循环的结果

Regex结果包含额外的match/group,只带一个返回

我的角模板订阅后不刷新'

如何避免页面第一次加载时由于CSS样式通过JavaScript更改而出现闪烁

如何使onPaste事件与可拖动的HTML元素一起工作?

在使用HighChats时如何避免Datatables重新初始化错误?

这个值总是返回未定义的-Reaction

Jest toHaveBeenNthCalledWith返回当前设置的变量值,而不是调用时的值

邮箱密码重置链接不适用于已部署的React应用程序

MarkLogic-earch.suggest不返回任何值

如何在Java脚本中对数据进行签名,并在PHP中验证签名?

JAVASCRIPT SWITCH CASE语句:当表达式为';ALL';

如何使用[ModelJSON,ArrayBuffer]调用tf.loadGraphModelSync