user17880803
user17880803

Reputation:

How to use setInterval() in react?

I'm trying to learn react and I am trying to create a working clock

import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

class App extends React.Component {
  render() {
    function tick() {
      return new Date().toLocaleTimeString();
    }
    return <h1>{tick()}</h1>; 
    //I want to use setInterval(tick, 1000) here so I can call the tick function every 1 sec
  }
}
export default App;

Thanks in advance

Upvotes: 0

Views: 224

Answers (4)

3limin4t0r
3limin4t0r

Reputation: 21160

All the answers so far are using function components. Since the question is asked using class components, let me use that as a starting point:

To re-render a component either the state or props must change. Your current solution does neither. To create a functioning clock we can store the current date inside a state. Then use setInterval() within the componentDidMount() lifecycle method to run tick() every 1 second. By updating the state in the tick() method we trigger a component re-render, thus displaying the newly set date.

It's also good practice to clean up any timeouts/intervals on component unmount, so we run clearInterval() within the componentWillUnmount() lifecycle method.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { now: new Date() };
  }
  tick() {
    this.setState({ now: new Date() });
  }
  
  componentDidMount() {
    this.intervalId = setInterval(() => this.tick(), 1000);
  }
  componentWillUnmount() {
    clearInterval(this.intervalId);
  }

  render() {
    return <h1>{this.state.now.toLocaleTimeString()}</h1>;
  }
}

ReactDOM.createRoot(document.querySelector("#root")).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>

Instead of class components we can also use function components in modern React (like the other answers show). Here is the above snippet translated into one that uses a functional component.

function App(props) {
  const [now, setNow] = React.useState(new Date());
  
  React.useEffect(() => {
    function tick() {
      setNow(new Date());
    }
    
    const intervalId = setInterval(tick, 1000);
    return () => clearInterval(intervalId);
  }, []);

  return <h1>{now.toLocaleTimeString()}</h1>;
}

ReactDOM.createRoot(document.querySelector("#root")).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>

Again, we'll use a state to store the date. Then we'll use useEffect to register the tick() as an interval. The return value of useEffect should be a function that cleans everything up. Note that the dependency list of useEffect is empty, which causes the content only to run on component mount (and the clean-up on unmount). See the useEffect documentation for details.

Upvotes: 0

Blazej Kita
Blazej Kita

Reputation: 135

I use useState, it's working perfect:

 const myFunc = () => {
                console.log('My process....');
        }

        const[internalID, setInternalID] = useState(   
            setInterval(myFunc, 1000 )  
         );

Upvotes: 0

Dae Hyeon Mun
Dae Hyeon Mun

Reputation: 536

Add this code :D

useEffect(() => {
    const timer = setInterval(tick, 1000);
    return () => clearInterval(timer)
}, [])

Upvotes: 0

Ivo
Ivo

Reputation: 2518

You should use setInterval in a useEffect and don't forget to return the clear interval from the useEffect so that it gets removed on unmount:

useEffect(() => {
  const interval = setInterval(() => {
    console.log('This will run every second!');
  }, 1000);
  return () => clearInterval(interval);
}, []);

Upvotes: 2

Related Questions