调用 clearTimeout 后触发的 React-Native setTimeout 函数

React-Native setTimeout function triggered after clearTimeout is called

在我的 react-native 应用程序中,我正在构建一个组件,该组件具有 'heads up display' 和一些控件,只有在触摸视图后才会出现。然后,在用户最后一次交互后的一秒钟,我希望这些按钮再次消失,以便看起来更干净。

我正在为此使用 setTimeout。每当用户与我的组件交互时,我都会触发一个函数。在这个函数中,我设置了一个超时时间为1秒,然后在触发时清除导航按钮。我还检查是否已经设置了另一个计时器(我将它们存储在状态中),然后取消它,因为我想确保只触发最新的超时功能。

这是代码:

const [timer, setTimer] = useState<number>(null)

const handleControlsInteraction = useCallback(() => {
    // If the user interacted with the controls, we need to make them disappear 1 second after the latest interaction

    // If a timer was already set by a previous interaction, we want to cancel it, 
    // because because the controls should disappear 1 second after the latest interaction
    if (timer != null) {
        console.log('Cancelling timeout: ', timer)
        clearTimeout(timer)
    }

    // now we set a new timer for 1 second
    let timeout = setTimeout(() => {
        // When the function of the timer triggers, we need to hide the controls, clear the timeout and remove the timout from our local state
        console.log('Hiding buttons for timeout: ', timeout)
        setDisplayButtons(false)
        clearTimeout(timer)
        setTimer(null)
    }, 1000);
    console.log('Setting new timeout: ', timeout)

    setTimer(timeout)
}, [timer])

当我 运行 这样做时,我点击我的控件两次(相隔半秒),我注意到我的第一个计时器按预期被取消了,但它的功能在那之后仍然被触发。这会导致我的控件在用户仍在与它们交互时隐藏,而不是在最近一次交互后 1 秒隐藏。

我想要实现的目标似乎是一件非常基本的事情。但是,我一直对此感到困惑。

我该如何解决这个问题?任何指导将不胜感激。

当您的组件更改状态并重新呈现时,新的 timeout 实例会重新创建并导致意外行为。

解决方案是跟踪每个组件重新呈现周期的原始超时实例。

React 为每个组件渲染周期提供 useRef 钩子以持久化值。

let timerRef = React.useRef(null);

useEffect(() => {
  // Clear the interval when the component unmounts
  return () => clearTimeout(timerRef.current);
}, []);

const handleControlsInteraction = () => {

  if (timerRef.current != null) {
    clearTimout(timerRef.current)
  }

  // now we set a new timer for 1 second
  timerRef.current = setTimeout(() => {
    setDisplayButtons(false);
  }, 1000);
};