渲染太多,反应 useInterval

发布于 2025-01-12 08:40:05 字数 1306 浏览 0 评论 0原文

我的 useInterval 钩子有以下问题,我试图让计数器在计数达到 20 时停止,但似乎我当前实现它的方式似乎会导致渲染无限循环。到目前为止,这是我的代码:

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

import { useInterval } from "usehooks-ts";

export default function Component() {
  // The counter
  const [count, setCount] = useState<number>(0);
  // Dynamic delay
  const [delay, setDelay] = useState<number>(1000);
  // ON/OFF
  const [isPlaying, setPlaying] = useState<boolean>(true);

  useInterval(
    () => {
      // Your custom logic here
      setCount(count + 1);
    },
    // Delay in milliseconds or null to stop it
    isPlaying ? delay : null
  );

  if (count === 10) {
    setPlaying(false);
  }

  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    setDelay(Number(event.target.value));
  };

  return (
    <>
      <h1>{count}</h1>
      <button onClick={() => setPlaying(!isPlaying)}>
        {isPlaying ? "pause" : "play"}
      </button>
      <p>
        <label htmlFor="delay">Delay: </label>
        <input
          type="number"
          name="delay"
          onChange={handleChange}
          value={delay}
        />
      </p>
    </>
  );
}

我无法理解为什么这不起作用,有人可以解释并告诉我我做错了什么吗?

I have the following problem with the useInterval hook, Im trying to make the counter stop if it hits count 20, but it seems that the way im currently implementing it it seems to cause infinite loop of render. here is my code so far:

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

import { useInterval } from "usehooks-ts";

export default function Component() {
  // The counter
  const [count, setCount] = useState<number>(0);
  // Dynamic delay
  const [delay, setDelay] = useState<number>(1000);
  // ON/OFF
  const [isPlaying, setPlaying] = useState<boolean>(true);

  useInterval(
    () => {
      // Your custom logic here
      setCount(count + 1);
    },
    // Delay in milliseconds or null to stop it
    isPlaying ? delay : null
  );

  if (count === 10) {
    setPlaying(false);
  }

  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    setDelay(Number(event.target.value));
  };

  return (
    <>
      <h1>{count}</h1>
      <button onClick={() => setPlaying(!isPlaying)}>
        {isPlaying ? "pause" : "play"}
      </button>
      <p>
        <label htmlFor="delay">Delay: </label>
        <input
          type="number"
          name="delay"
          onChange={handleChange}
          value={delay}
        />
      </p>
    </>
  );
}

I can't grasp on why this wont work, could someone explain and show me what im doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

策马西风 2025-01-19 08:40:05

代码中的以下块是导致无限循环的原因,因为在计数为 10 且计数器暂停后的每次渲染中,每次都会执行 setPlaying(false) 并导致每次重新渲染,从而导致无限循环

 if (count === 10) {
    setPlaying(false);
 }

相反,您可以将此块移动到使用效果,如

  useEffect(() => {
    if (count === 10) {
      setPlaying(false);
    }
  }, [count]);

Please find codesandbox 供参考

The following block in the code is what's causing the infinite loop, as on every render after the count is 10 and counter is paused, setPlaying(false) will be executed every time and will cause re render everytime, thus cause the infinite loop

 if (count === 10) {
    setPlaying(false);
 }

Instead you can move this block to a use effect as

  useEffect(() => {
    if (count === 10) {
      setPlaying(false);
    }
  }, [count]);

Please find codesandbox for reference

余生再见 2025-01-19 08:40:05

使用 useEffect 钩子:

useEffect(() => {
if (count === 10) {
    setPlaying(false);
  }
}, [count])

每次 count 更改时,useEffect 都会触发并检查 count 是否达到 10。

您还可以阻止用户更改高于 10 的状态:

<button onClick={() => setPlaying(count === 10 ? false : !isPlaying)}>

With a useEffect hook :

useEffect(() => {
if (count === 10) {
    setPlaying(false);
  }
}, [count])

Every time count changes, useEffect will trigger and check if count has reached 10.

You may also prevent user from changing state above 10 :

<button onClick={() => setPlaying(count === 10 ? false : !isPlaying)}>
尹雨沫 2025-01-19 08:40:05

每个更新状态或属性都会导致创建一个新的间隔。

如果您必须使用间隔

let myinterval = useInterval(
    () => {
      // Your custom logic here
      setCount(count + 1);
    },
    // Delay in milliseconds or null to stop it
    isPlaying ? delay : null
  );
clearInterval(myinterval);

请将此代码放入 useEffect

useEffect(()=>{
if(count <20){
let myinterval = useInterval(
    () => {
      // Your custom logic here
      setCount(count + 1);
    },
    // Delay in milliseconds or null to stop it
    isPlaying ? delay : null
  );

clearInterval(myinterval);
}
},[count])

each update state or props cause to create a new interval.

If you have to use interval

let myinterval = useInterval(
    () => {
      // Your custom logic here
      setCount(count + 1);
    },
    // Delay in milliseconds or null to stop it
    isPlaying ? delay : null
  );
clearInterval(myinterval);

you put this code to useEffect

useEffect(()=>{
if(count <20){
let myinterval = useInterval(
    () => {
      // Your custom logic here
      setCount(count + 1);
    },
    // Delay in milliseconds or null to stop it
    isPlaying ? delay : null
  );

clearInterval(myinterval);
}
},[count])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文