Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialKristian Woods
23,414 PointsHow do I properly update DOM elements in React.js?
I have a countdown component, and which to output a timer on the page. Right now, I'm using .innerHTML
to output the timer. However, I feel like thats wrong when it comes to React. Should I be using setState
instead? Or perhaps a different approach entirely?
My current approach has been to create a function countDownTimer
that takes a date and then counts down to that date. I'm then outputting that by invoking the function <p id="timer-output">{countDownTimer()}</p>
My main issue is how its being added to the DOM:
document.getElementById("timer-output").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
is there a cleaner way?
import React, { useContext } from 'react';
import { MasterContext } from '../contexts/masterContext';
const Timer = () => {
// endDate => 'Jan 18, 2020 15:37:25'
const { endDate } = useContext(MasterContext);
const countDownTimer = () => {
// Set the date we're counting down to
var countDownDate = new Date(endDate).getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Output the result in an element with id="demo"
document.getElementById("timer-output").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("timer-output").innerHTML = "EXPIRED";
}
}, 1000);
}
return (
<section id="timer">
<p id="timer-output">{countDownTimer()}</p>
</section>
);
}
export default Timer;
2 Answers
Steven Parker
231,269 PointsPerhaps a template literal is what you want:
document.getElementById("timer-output").innerHTML = `${days}d ${hours}h ${minutes}m ${seconds}s`;
Zimri Leijen
11,835 PointsA wrote a very simple React timer to show you the concept of how I would implement it using React. Note I'm not that experienced with React yet either, but this looks more 'clean'.
import React, { Component } from "react";
import "./styles.css";
class Clock extends Component {
constructor(props) {
super(props);
this.state = {
time: null
};
}
componentDidMount() {
this.intervalID = setInterval(() => this.setTime(), 1000);
}
componentWillUnmount() {
clearInterval(this.intervalID);
}
setTime() {
let time = new Date().toTimeString();
this.setState({ time });
}
render() {
return <div>{this.state.time}</div>;
}
}
export default function App() {
return <Timer />;
}
class Timer extends Component {
render() {
return <Clock />;
}
}
Zimri Leijen
11,835 PointsZimri Leijen
11,835 PointsWhile that is valid JavaScript and will work, that kind of defeats the purpose of using React.
Steven Parker
231,269 PointsSteven Parker
231,269 PointsPerhaps I misunderstood what you meant by "cleaner". So, perhaps the React-ish version might be: