简体   繁体   English

如何使用带有外部依赖项的 React useCallback 和 useEffect

[英]How to use React useCallback and useEffect with outside dependencies

I am trying to follow react-plugin-react-hooks.我正在尝试关注 react-plugin-react-hooks。

I have a useEffect which adds an event listener to the window ( onScroll ).我有一个useEffect ,它向window ( onScroll ) 添加了一个事件侦听器。 onScroll makes use of window.pageYOffset . onScroll使用window.pageYOffset

function onScroll() {
    if (window.pageYOffset > 0) {
      setFoor(bar)
    } else {
      setFoor(baz)
    }
  }

Now in the useEffect I have:现在在useEffect我有:

useEffect(() => {
    window.addEventListener('scroll', onScroll);
    onScroll();
    return () => {
      window.removeEventListener('scroll', onScroll);
    };
  }, []);

This was following the idea initially supported recommendation that if you pass an empty dependency array, it's like componentDidMount .这是遵循最初支持的建议,即如果您传递一个空的依赖数组,它就像componentDidMount一样。 But the React docs clearly say that you should either pass no dependencies (not even empty array), or all dependencies (which refer to props or state).但是 React 文档清楚地表明你应该不传递任何依赖项(甚至不传递空数组),或者所有依赖项(引用 props 或 state)。 ( https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies ) So that would look like: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies )所以看起来像:

useEffect(() => {
    window.addEventListener('scroll', onScroll);
    onScroll();
    return () => {
      window.removeEventListener('scroll', onScroll);
    };
  }, [onsScroll]);

But that means I have to use useCallback for onScroll or it will always have a different depenedency.但这意味着我必须对onScroll使用useCallback ,否则它将始终具有不同的依赖关系。 But the useCallback "dependency" for onScroll would be window.pageYOffset , but that doesn't work, ie:但是 onScroll 的useCallback “依赖项”将是onScroll ,但这window.pageYOffset ,即:

function onScroll = React.useCallback(() => {
    if (window.pageYOffset > 0) {
      setFoor(bar)
    } else {
      setFoor(baz)
    }
  }, [window.pageYOffset])

My general question, is how do you deal with useEffect / useCallback functions that had outside dependencies?我的一般问题是,您如何处理具有外部依赖关系的useEffect / useCallback函数? (Besides ignore the warning.) (除了忽略警告。)

Thanks谢谢

I also tried moving onScroll definition entirely inside the useEffect but it doesn't update properly.我还尝试将onScroll定义完全移动到useEffect中,但它没有正确更新。

useEffect(() => {
    function onScroll() {
      if (window.pageYOffset > 0 && !slim) {
        setSlim(true);
      } else {
        setSlim(false);
      }
    }
    window.addEventListener('scroll', onScroll, onScrollOptions);
    onScroll();
    getAccountAction();
    return () => {
      window.removeEventListener('scroll', onScroll, onScrollOptions);
    };
  }, []);

Dependencies should be props or state, here you have a class method defined as a dependency, in your case I suppose you want to mount the event listener with a effect similar to componentDidMount, you can achieve that by setting an empty array as a dependency.依赖项应该是 props 或 state,在这里你有一个定义为依赖项的 class 方法,在你的情况下,我想你想挂载事件监听器,其效果类似于 componentDidMount,你可以通过将空数组设置为依赖项来实现。 In this case this is not wrong as the logic in the effect doesn't use any variables in the component scope.在这种情况下,这并没有错,因为效果中的逻辑不使用组件 scope 中的任何变量。

In the event handler I would change state by setting the value of the pageoffset and in the other effect use that state as the dependency在事件处理程序中,我将通过设置 pageoffset 的值来更改 state 并在其他效果中使用 state 作为依赖项

Even if you define scroll handler inside useEffect , you're still accessing the offset from outside, which you need to track inside the dependencies array as well as the slim state var.即使您在useEffect中定义了滚动处理程序,您仍然可以从外部访问偏移量,您需要在依赖项数组以及slim的 state var 中跟踪它。

Your onScroll function can be simplified by using functional form of setState , in which case you won't need to track slim state variable anymore:您的 onScroll function 可以通过使用setState的函数形式来简化,在这种情况下,您将不再需要跟踪slim state 变量:

useEffect(() => {
  function onScroll() {
    setSlim(currentSlim => window.pageYOffset > 0 && !currentSlim)
  }

  window.addEventListener('scroll', onScroll, onScrollOptions);
  getAccountAction();
  return () => {
    window.removeEventListener('scroll', onScroll, onScrollOptions);
  };
}, [window.pageYOffset]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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