首页 > 解决方案 > UseEffect 不会使用更新的状态

问题描述

我有一个反应函数,它应该是我的标题。到达滚动按钮后,此标题应更改其背景颜色。

为此,我使用滚动事件侦听器并跟踪其相对于按钮的位置。这适用于setTransparent(false),但不适用于setTransparent(true)即使将侦听器设置为第一个 if 语句内部,
日志记录也会返回。transparenttruefalse

怎么会这样?这里的最佳做法是什么?

const [transparent, setTransparent] = useState(true);

useEffect(() => {
    const button = document.querySelector(".hero-button");

    window.addEventListener("scroll", () => {
        const {bottom} = button.getBoundingClientRect();

        if (transparent && bottom <= 0) {
            setTransparent(false);
        } else if (!transparent && bottom > 0) {
            setTransparent(true);
        }
    });
}, [])

将依赖项设置为transparent将使其工作,但这将在每次更新时添加甚至监听器。

标签: javascriptreactjs

解决方案


transparent在效果回调中的变量仅引用初始渲染上的值,该值始终为true. 您可以通过在更改时重新添加滚动侦听器来修复它transparent,并返回一个删除先前处理程序的清理函数:

useEffect(() => {
    const button = document.querySelector(".hero-button");
    const scrollHandler = () => {
        const { bottom } = button.getBoundingClientRect();

        if (transparent && bottom <= 0) {
            setTransparent(false);
        } else if (!transparent && bottom > 0) {
            setTransparent(true);
        }
    };
    window.addEventListener("scroll", scrollHandler);
    // DON'T FORGET THE NEXT LINE
    return () => window.removeEventListener("scroll", scrollHandler);
}, [transparent]);

另一种选择是使用 ref 而不是useState透明的(或者,useState如果transparent更改需要导致重新渲染)。


推荐阅读