React状态改变时重新应用所有事件侦听器是否不好

时间:2018-12-17 08:10:07

标签: javascript reactjs react-hooks

我有一个钩子,可使用滚轮或keyup事件在React应用程序中更改页面。最后,我来到了这个有效的解决方案:

function useScrollingPage (pages) {
    const [page, setPage] = useState(0);
    const wheelHandler = (event) => {
        // some logic
        setPage(page + 1);
    };
    useEffect(
        () => {
            window.addEventListener(EVENTS.WHEEL, wheelHandler);
            window.addEventListener(EVENTS.KEY_UP, keyHandler);

            return () => {
                window.removeEventListener(EVENTS.WHEEL, wheelHandler);
                window.removeEventListener(EVENTS.KEY_UP, keyHandler);
            };
        },
        [page],
    );

    return page;
}

但是,在处理它时,我遇到了几次迭代。

  1. 我会在addEventListener之外给useEffect打电话。这样,一切正常,但是侦听器永远不会被删除。
  2. 我将传递一个空数组作为useEffect的第二个参数。这样,它只能在组件安装上运行,但不会更改page中的wheelHandler引用,因此它将始终尝试将页面设置为1(setPage(0 + 1)
  3. 每次page更改时都运行useEffect。它可以工作,但是每次状态更改时都删除并添加所有侦听器并不恰当。

每次状态更改时添加/删除事件侦听器对性能是否有害?像这样的问题的最佳解决方案是什么?

1 个答案:

答案 0 :(得分:0)

根据文档,当侦听器依赖状态或要订阅的道具时,您可能希望使用上述模式,但是在上述情况下,您可以使用状态更新的回调模式并传递一个空数组作为useEffect

的第二个参数
function useScrollingPage (pages) {
    const [page, setPage] = useState(0);
    const wheelHandler = (event) => {
        // some logic
        setPage(page => page + 1);
    };
    useEffect(
        () => {
            window.addEventListener(EVENTS.WHEEL, wheelHandler);
            window.addEventListener(EVENTS.KEY_UP, keyHandler);

            return () => {
                window.removeEventListener(EVENTS.WHEEL, wheelHandler);
                window.removeEventListener(EVENTS.KEY_UP, keyHandler);
            };
        },
        [],
    );

    return page;
}

但是,当您编写上述逻辑时,请确保未在wheelHandler中使用状态。如果是这样,那么您将遵循适合您的模式并建议这样做。