0

我在函数组件中有以下钩子。

  useEffect(() => {
    if (isMinimized) {
      // When minimizing, delay swapping the element to the minimized node.
      // This gives the video takeover minimize animation time to run and results
      // in a more seamless looking video swap
      if (videoMinimizedRef.current !== null) {
        setTimeout(() => {
          setOuterContainer(minimizedVideoRef.current);
        }, VIDEO_OVERLAY_VIDEO_ELEMENT_SWAP_TIMEOUT);
      }
    } else {
      // When maximizing, immediately swap the video element to the maximized
      // node. This ensures the video element is present at the start of the animation.
      if (videoMaximizedCallbackRef !== null) {
        setOuterContainer(videoMaximizedCallbackRef);
      }
    }
  }, [isMinimized, setOuterContainer, videoMinimizedRef, videoMaximizedCallbackRef]);

isMinimized, setOuterContainer, videoMinimizedRef都是传递给组件的道具。

  • isMinimized是一个布尔值
  • setOuterContainer是一个 useState setter 函数,它接收一个 HTMLElement 并将其设置为正在播放的视频元素的新父节点。
  • videoMinimizedRef是最小化播放时对视频容器的引用。

videoMaximizedCallbackRef.current是在此组件中设置的回调 ref(没有)。

钩子按原样工作,完全符合我的要求。也就是说,我意识到这个钩子有一些问题(至少从阅读 React 钩子文档和常见问题解答看来是这样)。例如,没有清理 setTimeout。可以这样添加:

  useEffect(() => {
    let timeout;
    if (isMinimized) {
      // When minimizing, delay swapping the element to the minimized node.
      // This gives the video takeover minimize animation time to run and results
      // in a more seamless looking video swap
      if (videoMinimizedRef.current !== null) {
        timeout = setTimeout(() => {
          setOuterContainer(minimizedVideoRef.current);
        }, VIDEO_OVERLAY_VIDEO_ELEMENT_SWAP_TIMEOUT);
      }
    } else {
      // When maximizing, immediately swap the video element to the maximized
      // node. This ensures the video element is present at the start of the maximize animation.
      if (videoMaximizedCallbackRef !== null) {
        setOuterContainer(videoMaximizedCallbackRef);
      }
    }
    return () => clearTimeout(timeout);
  }, [isMinimized, setOuterContainer, videoMinimizedRef, videoMaximizedCallbackRef]);

但是添加它会导致每次任何依赖项更改时都会清除超时。我需要确保超时在启动时永远不会被清除,因为它会导致视频交换在不完全正确之后发生

VIDEO_OVERLAY_VIDEO_ELEMENT_SWAP_TIMEOUT女士,而是

VIDEO_OVERLAY_VIDEO_ELEMENT_SWAP_TIMEOUT + sum of time passed in previous cleared setTimeouts小姐

clearTimeout我怎样才能以一种避免过时闭包和不需要的调用的陷阱的方式编写这个钩子?

我想遵守钩子和详尽依赖项的规则,但这对我来说有点太多了。

4

2 回答 2

0

你正在做的方式会很好。设置间隔时,这不是正确的方法,但对于超时,它就像一个魅力。

useEffect(() => {
  let timeout;
  timeout = setTimeout(() => {
    // set timeout callback, write your code here
  }, 100)

  return () => {
    clearTimeout(timeout)
  }
}, [yourDependencies])

您可以从 dan abramov 的博客中了解更多信息:https ://overreacted.io/a-complete-guide-to-useeffect/

于 2020-01-30T18:27:33.143 回答
0

如果你有一个事件有超时但你也可以清除那个事件,这表明使用需要查看使用

间隔定时器设置一次,按间隔重复

tRef = setInterval(theFuncCall,timeMills)

并清除

clearInterval( tRef );

如果您正在查看 100 毫秒的调用间隔,那么您应该将setInterval其用作控制时间的选项。

于 2020-01-30T18:38:31.820 回答