Reputation:
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
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
Reputation: 135
I use useState, it's working perfect:
const myFunc = () => {
console.log('My process....');
}
const[internalID, setInternalID] = useState(
setInterval(myFunc, 1000 )
);
Upvotes: 0
Reputation: 536
Add this code :D
useEffect(() => {
const timer = setInterval(tick, 1000);
return () => clearInterval(timer)
}, [])
Upvotes: 0
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