UseEffect将不使用更新状态

时间:2020-10-29 19:11:47

标签: javascript reactjs

我有一个应为我的标头的react函数。到达滚动按钮后,此标题将更改其背景颜色。

为此,我使用滚动事件侦听器并跟踪其相对于按钮的位置。这对于setTransparent(false)来说是很好的方法,但对setTransparent(true)来说则不是:
在监听器中记录transparent会返回true,即使将其设置为{{1 }}内的第一个if语句中。

如何?这里的最佳做法是什么?

false

将依赖项设置为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); } }); }, []) 将使其起作用,但这将在每次更新时甚至添加侦听器。

1 个答案:

答案 0 :(得分:2)

效果回调中的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之外的符号)。