Reputation: 2743
I'm new to React, I'm trying to follow this ticking clock example but do something a bit different. I'd like the ReactDOM
to be rendered in the index.js
. Here is my code:
Timer.js:
import React from 'react';
const Timer = () => {
const tick = () => {
return new Date().toLocaleTimeString().toString();
};
const element = (
<div>
<h1>Hello World!</h1>
<h2>It is {tick()} !</h2>
</div>
);
return (
element
);
};
export default Timer;
App.js:
/*jshint esversion: 8 */
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Timer from './Timer'
function App() {
return (
<div className="App">
<Timer />
</div>
);
}
export default App;
index.js:
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import * as serviceWorker from "./serviceWorker";
import App from './App';
setInterval(ReactDOM.render(<App />, document.getElementById("root")), 1000);
serviceWorker.unregister();
But it only prints the current time on screen, not ticking. Why does the code setInterval(ReactDOM.render(<App />, document.getElementById("root")), 1000);
not work on index.js
?
Upvotes: 1
Views: 245
Reputation: 303
It is a good practice to avoid calling directly the render function, you could make your Timer
a Component and let it update with state changes, which is how react would do it with its life cycle. For example:
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = {
time: new Date().toLocaleTimeString().toString()
};
}
tick() {
this.setState({
time: new Date().toLocaleTimeString().toString()
});
}
componentDidMount() {
this.intervalID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.intervalID);
}
render() {
return (
<div>
<h1>Hello World!</h1>
<h2>It is {this.state.time} !</h2>
</div>
);
}
}
export default Timer;
Notice I used two of React cycle functions componentDidMount
and componentWillUnmount
, in order to make the component update once again after finished mouting, and the other to clear the interval variable once react unmounts your component.
Upvotes: 3
Reputation: 12129
You can use React.useEffect
passing an array as second argument, which is the equivalent of componentDidMount
.
You then want to use setInterval
to set the state every second.
Return a function from useEffect
to clear the interval when the component unmounts.
See working codesandbox here.
You code would look as follows:
const function Timer() {
const [time, setTime] = React.useState(null);
React.useEffect(() => {
const tick = () => {
return new Date().toLocaleTimeString().toString();
};
const intervalId = setInterval(() => {
setTime(tick());
return () => clearInterval(intervalId);
}, 1000);
}, []);
return <h2>It is {time} !</h2>;
}
Upvotes: 2
Reputation: 137
Set the date field to the state object and in tick function use setInterval to set a new value to state using setState. Use state.date value to show the time. React renders new dom each time state is changed using setState function.
A working example of a timer has been given in react docs, giving it a read will help you lots. https://reactjs.org/docs/state-and-lifecycle.html
Upvotes: 1