最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React setInterval and useState - Stack Overflow

programmeradmin5浏览0评论

I have 2 question. First, why this code does not work. Second, why this code slow when it comes 2^n -1 for example 1-3-7-15

let time = 0
function App() {
  const [mytime, setMytime] = useState(time)
  setInterval(() => {
    time += 1
    setMytime(time)
  }, 1000)
  return <div> {mytime} </div>

I have 2 question. First, why this code does not work. Second, why this code slow when it comes 2^n -1 for example 1-3-7-15

let time = 0
function App() {
  const [mytime, setMytime] = useState(time)
  setInterval(() => {
    time += 1
    setMytime(time)
  }, 1000)
  return <div> {mytime} </div>
Share Improve this question asked Feb 18, 2022 at 11:20 PYigitPYigit 1701 gold badge2 silver badges8 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 14

Issue

The setInterval gets called each time when mytime changes for rerendering (when you call the setMytime). And the number of setInterval calls grows exponentially. This would lead to a memory leak as well.

Solution

You should run it only once. You should use useEffect hook with an empty dependency array.

Try like this.

import { useEffect, useState } from "react";

function App() {
  const [mytime, setMytime] = useState(0);

  useEffect(() => {
    // create a interval and get the id
    const myInterval = setInterval(() => {
      setMytime((prevTime) => prevTime + 1);
    }, 1000);
    // clear out the interval using the id when unmounting the component
    return () => clearInterval(myInterval);
  }, []);

  return <div> {mytime} </div>;
}

export default App;

To extend @Amila's answer,

What if you want to start, stop, reset timer using functions ?
  1. Make sure you use useRef(), because useState() will cause render.
  2. Make sure you unmount the interval in the useState() as it will cause skipping of timer.
    useEffect(() => {
         return () => clearInterval(currentTimer.current);
     }, []);
    

Use the following code:

    const [time, setTime] = useState(0);
    const currentTimer = useRef();
    useEffect(() => {
        return () => clearInterval(currentTimer.current);
    }, []);
    const startTimer = () => {
        currentTimer.current = setInterval(() => {
            setTime((prev) => prev + 1);
            console.log(time);
        }, 1000);
    };
    const stopTimer = () => {
        clearInterval(currentTimer.current);
    };
    const resetTimer = () => {
        clearInterval(currentTimer.current);
        setTime(0);
    };
    return (
        <div>
            <div>{time}</div>
            <button onClick={startTimer}>Start</button>
            <button onClick={stopTimer}>Stop</button>
            <button onClick={resetTimer}>Reset</button>
        </div>
    );
发布评论

评论列表(0)

  1. 暂无评论