使用函数式 Hooks 的 React Timer |定时器没有停止 [英] React Timer using functional Hooks | Timer is not stopping

查看:15
本文介绍了使用函数式 Hooks 的 React Timer |定时器没有停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用钩子 useStateuseEffects 在 React 上创建一个 60 秒的时间,这就是我正在做的

import '../assets/css/timer.css'import { useState, useEffect } from 'react'const 定时器 = () =>{const [时间,setTime] = useState(0);useEffect(()=>{如果(时间!==60){setInterval(()=>{setTime(prevTime => prevTime+1) ;}, 1000);}}, [])返回(<><div className="圆形"><div className="inner"></div><div className="outer"></div><div className="numb">{time}//显示时间的地方

<div className="圆圈"><div className="点"><span></span>

<div className="bar left"><div className="progress"></div>

<div className="右侧栏"><div className="progress"></div>

</>)}导出默认定时器

定时器没有停止.它永远持续下去.我也试过这个

 useEffect(()=>{setInterval(()=>{如果(时间!==60)setTime(prevTime => prevTime+1) ;}, 1000);}, [])

能否请一些人解释一下哪里出了问题.

解决方案

您的第一次尝试已接近成功,但存在一些问题.

主要问题是您传递了一个空的依赖数组,这意味着它只会在第一次渲染时运行,而不会在后续渲染时更新.其次,您不提供返回或清理",这意味着该间隔永远不会被清除.

 useEffect(() => {如果(时间<60){const timer = setInterval(() => {setTime(prevTime => prevTime + 1);}, 1000);返回 () =>清除间隔(定时器);}}, [时间])

这里我们在依赖数组中传递 time 并有条件地设置间隔,如果 time 小于您的结束时间,在您的情况下为 60,但我将其缩短为 5 所以你可以看到它停止.我们还传递了一个 return 回调,它将在每个渲染周期结束时清除间隔.

设置每次 setInterval 更新 time 状态后,useEffect 将清除前一次渲染结束时的间隔,然后在当前渲染中重新运行,再次设置间隔,如果时间小于限制.

以这种方式使用 React 渲染周期的优点,而不是清除间隔回调中的间隔,是它可以让您对超时进行精细控制 - 允许您轻松添加进一步检查或延长/缩短基于其他状态值.

const { useState, useEffect } = React;const 定时器 = () =>{const [time, setTime] = useState(0);useEffect(() => {如果(时间<5){const timer = setInterval(() => {setTime(prevTime => prevTime + 1);}, 1000);返回 () =>清除间隔(定时器);}}, [时间])返回 (<div className="圆形"><div className="numb">{时间}

)}ReactDOM.render(<定时器/>,document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script><div id="root"></div>

I want to create a time of 60s on react using hooks useState and useEffects This is what i am doing

import '../assets/css/timer.css'
import { useState, useEffect } from 'react'

const Timer = () =>{

    const [ time, setTime ] = useState(0);

    useEffect(()=>{
        if(time!==60){
            setInterval(()=>{
                    setTime(prevTime => prevTime+1) ;
            }, 1000);
        }
        
    
    }, [])


    return(
        <>

            <div className="circular">
                <div className="inner"></div>
                <div className="outer"></div>
                <div className="numb">
                    {time}  // Place where i am displaying time
                </div>
                <div className="circle">
                    <div className="dot">
                    <span></span>
                    </div>
                    <div className="bar left">
                    <div className="progress"></div>
                    </div>
                    <div className="bar right">
                    <div className="progress"></div>
                    </div>
                </div>
            </div>
        </>
    )
}

export default Timer

Timer is not stopping. It continues to go on for ever. I have tried this too

    useEffect(()=>{

        setInterval(()=>{
            if(time!==60)
                setTime(prevTime => prevTime+1) ;
        }, 1000);
    
    }, [])

Can some please explain where things are going wrong.

解决方案

You are close to having it working with your first attempt, but there are a few problems.

The main problem is that you pass an empty dependency array, meaning it will only run on the first render and not be updated on successive renders. Secondly you don't provide a return or 'clean up' meaning the interval is never cleared.

  useEffect(() => {
    if (time < 60) {
      const timer = setInterval(() => {
        setTime(prevTime => prevTime + 1);
      }, 1000);

      return () => clearInterval(timer);
    }
  }, [time])

Here we pass time in the dependency array and conditionally set the interval if time is less than your end time, 60 in your case but I shortened it to 5 so that you can see it stop. We also pass a return callback that will clear the interval at the end of each render cycle.

With this set up every time the setInterval updates the time state the useEffect will clear the interval at the end of the previous render, and then re-run in the current render setting the interval again if time is less than the limit.

The advantage of using the React render cycle this way, instead of clearing the interval in the interval callback, is that it gives you granular control of your timeout – allowing you to easily add further checks or extend/shorten the time based on other state values.

const { useState, useEffect } = React;

const Timer = () => {
  const [time, setTime] = useState(0);

  useEffect(() => {
    if (time < 5) {
      const timer = setInterval(() => {
        setTime(prevTime => prevTime + 1);
      }, 1000);

      return () => clearInterval(timer);
    }
  }, [time])

  return (
    <div className="circular">
      <div className="numb">
        {time}
      </div>
    </div>
  )
}

ReactDOM.render(
  <Timer />,
  document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

<div id="root"></div>

这篇关于使用函数式 Hooks 的 React Timer |定时器没有停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆