【问题标题】:How to clearTimeout properly如何正确清除超时
【发布时间】:2019-09-22 05:47:54
【问题描述】:

我有这个功能可以在帖子中添加拍手。我不想每次拍手都拍手,因为这在我的 mysql 服务器上会很疯狂,更不用说 http 请求和重新渲染了。相反,我想让鼓掌加起来一点,只有当用户停止添加鼓掌几秒钟,然后将鼓掌添加到数据库中。所以我的函数将拍手正确地存储在状态中,但它每次都在运行该函数并且从不清除超时。

  let sendClapsToDB

  _clapForPost = (postId) => {

    clearTimeout(sendClapsToDB)

    setClaps(() => claps + 1)

    sendClapsToDB = setTimeout(() => {
      _addClapsToPost(claps, postID)
    }, 5000)
  }

有谁知道如何正确执行此操作。我正在使用 React Native 并获取。每次用户按下按钮时都会调用 _clapForPost 函数。

【问题讨论】:

  • 一个好的做法是将var是容器重置为null,此方法将推送到垃圾收集器sendClapsToDB
  • @ÁlvaroTouzón - 感谢您的尝试 - 但没有奏效。
  • 尝试使用var 而不是let。您示例中的变量 sendClapsToDB 位于两个不同的范围内。也许不是最好的解决方案,但应该可行!
  • @FrancescoSimeoli - 试过了 - 没用

标签: javascript react-native settimeout cleartimeout


【解决方案1】:

如果您使用的是类组件,您可以尝试这样的方式。

import React from "react";


class App extends React.Component {
  state = {claps: 0}
  timeout = null;
  sendClap = () => {
    this.setState({claps: this.state.claps + 1})
    if(!this.timeout){
      this.timeout = setTimeout(() => {
        console.log("Send claps", this.state.claps);
        clearTimeout(this.timeout);
        this.timeout = null;
      }, 3000)
    }
  }

  render(){
    console.log(this.state.claps);
    return <button onClick={this.sendClap}>Clap</button>

  }
}

export default App;

我正在清除计时器,因为它运行并在下一次状态更新中重新初始化。 组件卸载时也需要清空定时器。

如果您使用带有钩子的功能组件,您可以尝试类似

import React, {useState, useRef} from "react";


export default () => {
  const [claps, setClaps] =  useState(0);
  const clapsRef = useRef(0);
  clapsRef.current = claps;
  const timeout = useRef(null);
  const sendClap = () => {
    setClaps(claps + 1);
    if(!timeout.current){
      timeout.current = setTimeout(() => {
        console.log("Send claps", clapsRef.current);
        clearTimeout(timeout.current);
        timeout.current = null;
      }, 3000)
    }
  }

    console.log(claps);
    return <button onClick={sendClap}>Clap</button>

}

这里我使用 useState 重新渲染组件,并使用 useRef 捕获最新状态以进行超时以获取最新状态参考。

【讨论】:

  • 我正在使用钩子使用功能组件 - 但是,我尝试使用 setClapsTimeout(null) 转换您的答案,然后将 setClapsTimeout 设置为超时函数,但这也不起作用。稍有不同的是,它将第一个掌声记录到数据库中,然后等待剩余的掌声并将它们加在一起。不太清楚我哪里出错了。
  • 更新了使用钩子的答案。让我知道这是否有帮助。另请参阅有关在类和函数组件中使用超时的文章。一篇很长的文章,但可能值得。 (overreacted.io/…)
  • 我认为这可能有效!我现在要去睡觉了,但会在早上做更多的测试。如果一切正常,我将标记为正确并回复您。非常感谢您的帮助!
  • 这个答案非常好,效果很好。我还阅读了您提到的文章,这对理解为什么会起作用非常有帮助,尤其是关于使用 useRef 的部分。再次感谢!
  • 我确实找到了需要的编辑...当用户开始鼓掌时,它会设置计时器,这意味着无论如何它都会在 3 秒内运行。如果用户在 3 秒后仍然在鼓掌,它将运行该功能,然后在另外 3 秒内再次运行它。为了解决这个问题,我必须将clearTimeout(timeout.current)timeout.current = null 行复制到sendClap 函数的开头,以便每次有人鼓掌时它都会设置超时函数,并且在用户停止鼓掌之前它不会运行3 秒。
猜你喜欢
  • 1970-01-01
  • 2019-07-25
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多