admin管理员组

文章数量:1391981

I tried to create a simple timer app with ReactJS and found the below code on the internet.

Does the function that we passed to the useEffect will execute with the dependency change or does it recreates with every dependency change and then execute?

Also I console log the return function of the useEffect and it runs with every render. Does it run only when the ponent unmount? or with every render?

import { useEffect,  useState } from "react";

const App = () => {
  const [isActive, setIsActive] = React.useState(false);
  const [isPaused, setIsPaused] = React.useState(true);
  const [time, setTime] = React.useState(0);

  React.useEffect(() => {
    let interval = null;

    if (isActive && isPaused === false) {
      interval = setInterval(() => {
        setTime((time) => time + 10);
      }, 10);
    } else {
      clearInterval(interval);
    }
    return () => {
      console.log("cleanup");
      clearInterval(interval);
    };
  }, [isActive, isPaused]);

  const handleStart = () => {
    setIsActive(true);
    setIsPaused(false);
  };

  const handlePauseResume = () => {
    setIsPaused(!isPaused);
  };

  const handleReset = () => {
    setIsActive(false);
    setTime(0);
  };

  return (
    <div className="stop-watch">
      {time}
      <button onClick={handleStart}>start</button>
      <button onClick={handlePauseResume}>pause</button>
      <button onClick={handleReset}>clear</button>
    </div>
  );
};

export default App;

I tried to create a simple timer app with ReactJS and found the below code on the internet.

Does the function that we passed to the useEffect will execute with the dependency change or does it recreates with every dependency change and then execute?

Also I console log the return function of the useEffect and it runs with every render. Does it run only when the ponent unmount? or with every render?

import { useEffect,  useState } from "react";

const App = () => {
  const [isActive, setIsActive] = React.useState(false);
  const [isPaused, setIsPaused] = React.useState(true);
  const [time, setTime] = React.useState(0);

  React.useEffect(() => {
    let interval = null;

    if (isActive && isPaused === false) {
      interval = setInterval(() => {
        setTime((time) => time + 10);
      }, 10);
    } else {
      clearInterval(interval);
    }
    return () => {
      console.log("cleanup");
      clearInterval(interval);
    };
  }, [isActive, isPaused]);

  const handleStart = () => {
    setIsActive(true);
    setIsPaused(false);
  };

  const handlePauseResume = () => {
    setIsPaused(!isPaused);
  };

  const handleReset = () => {
    setIsActive(false);
    setTime(0);
  };

  return (
    <div className="stop-watch">
      {time}
      <button onClick={handleStart}>start</button>
      <button onClick={handlePauseResume}>pause</button>
      <button onClick={handleReset}>clear</button>
    </div>
  );
};

export default App;
Share Improve this question edited Jan 14, 2022 at 11:56 evolutionxbox 4,1326 gold badges38 silver badges57 bronze badges asked Jan 14, 2022 at 11:48 Dinuka DilshanDinuka Dilshan 1,2701 gold badge13 silver badges14 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

The code inside the useEffect hook will run every time a dependency value has been changed. In your case whenever isActive or isPaused changes state.

This means that the reference to the interval will be lost, as the interval variable is redefined.

To keep a steady reference, use the useRef hook to have the reference persist throughout state changes.

const App = () => {
  const [isActive, setIsActive] = useState(false);
  const [isPaused, setIsPaused] = useState(true);
  const [time, setTime] = useState(0);
  const interval = useRef(null)

  useEffect(() => {
    if (isActive && !isPaused) {
      interval.current = setInterval(() => {
        setTime((time) => time + 10);
      }, 10);
    } else {
      clearInterval(interval.current);
      interval.current = null;
    }

    return () => {
      clearInterval(interval.current);
    };
  }, [isActive, isPaused])

  ...
}
import React, { useState, useEffect } from "react";

/**
 * Timer ponent
 * 
 * Displays current time and allows user to enter their name
 */
export default function Timer() {
    const [time, setTime] = useState(0); // current time
    const [name, setName] = useState(""); // user's name

    /**
     * Set up an interval to update the time every second
     * 
     * Returns a function to clear the interval when the ponent unmounts
     */
    useEffect(() => {
        const intervalId = setInterval(() => {
            setTime((prev) => prev + 1);
        }, 1000);

        return () => {
            clearInterval(intervalId);
        };
    // Only run this effect once, on mount
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    /**
     * Handle changes to the input field
     *
     * @param {Object} event - input change event
     */
    const handleChange = ({ target }) => setName(target.value);

    return (
        <>
            <h1>Time: {time}</h1> {/* Display the current time */}
            <input value={name} onChange={handleChange} type="text" /> {/* Display the input field */}
        </>
    );
}

本文标签: javascriptHow to use setInterval with react useEffect hook correctlyStack Overflow