【问题标题】:how can I stop a function from calling itself? (React)如何阻止函数调用自身? (反应)
【发布时间】:2021-05-27 13:47:34
【问题描述】:

我有一个类似于分页的自动化功能,当它被按下时它会不断将数据推送到数据库中,它会按照我想要的方式工作,我唯一的问题是它无法停止,我试过了将 if 语句放在任何看起来合乎逻辑的地方,但我无法停止。 我将automate 设置为timeout 推送,因为如果没有,它会执行无限循环并尝试以超快的速度推送所有项目。

function automatePush() {
    if (stop === true) return console.log("stoppped");
    setMutationState(true); // this is what allowes the products to be pushed
    setSliceStart((prev) => prev + 5); //pagination start
    setSliceEnd((prev) => prev + 5); //pagination end
    if (stop === false){ // if stop is not true then keep calling the function 
      setTimeout(() => {
        setMutationState(false); // this just refreshes the item to keep pushing the next ones
        automatePush(); // this calls itself to keep looping through items.
      }, 6000);
    }
  }

如果我在执行automate 之前手动将stop 状态更改为true,然后单击automate,它会在控制台记录'stoppped',并且自动化不会发生,因为这是我想要的

这就是我在自动化进行时试图阻止它的方式

        <div>
          <p>
            by clicking "Automate" you can create all the products from the
            database (not including the ones you just created)
          </p>
          <button onClick={() => automatePush()}>Automate</button>  // this is the one that calls the automate
          <button onClick={() => setStop(true)}>STOP</button> // this one is the one that should stop it
        </div>

【问题讨论】:

标签: reactjs function state


【解决方案1】:

发生这种情况是因为 automatePush 每次都使用相同的 closure ,而初始 automatePush 具有并且 stop 的值在该闭包中没有改变。

使用ref 而不是state 来保存stop 值。请参见下面的示例。我已经修改了您的代码以使其正常工作。

const stop = useRef(true);

function automatePush() {
  if (stop.current) return console.log("stoppped");
  setMutationState(true);
  setSliceStart((prev) => prev + 5);
  setSliceEnd((prev) => prev + 5);
  setTimeout(() => {
    setMutationState(false);
    automatePush();
  }, 6000);
}

<div>
  <p>
    by clicking "Automate" you can create all the products from the database (not including the ones you just created)
  </p>
  <button 
    onClick={() => {
      stop.current = false;
      automatePush();
    }
  >Automate</button> 
  <button onClick={() => stop.current = true}>STOP</button>
</div>

~祈祷文

【讨论】:

  • 最好使用超时 id 而不是布尔值。但这样一来,它就可以与 React 一起使用。
  • @SirXtC 我很高兴它对你有用。
【解决方案2】:

记得在 useEffect 返回函数中清除超时 (stopPushing)。

const [timeoutId, setTimeoutId] = useState(null)

const automatePush = () => {
  setMutationState(true)
  setSliceStart((prev) => prev + 5)
  setSliceEnd((prev) => prev + 5)
  const id = setTimeout(() => {
    setMutationState(false)
    automatePush()
  }, 6000)
  setTimeoutId(id)
}

const stopPushing = () => clearTimeout(timeoutId)

useEffect(() => {
  return () => clearTimeout(timeoutId)
}, [])
<div>
   <button onClick={() => automatePush()}>Automate</button>
   <button onClick={() => stopPushing()}>STOP</button>
</div>

【讨论】:

    猜你喜欢
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    相关资源
    最近更新 更多