Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
In this article, we are going to make a stopwatch in react. Like a basic stopwatch we will have a display to show time, then we will have basic buttons for start, stop, resume and reset. As soon we will hit the start button, timer will be started and two buttons will appear stop and reset. By clicking stop, the timer will be stopped, and a resume button will appear. Lastly, the reset button will reset the timer back to 0 again.
So basically this is going to be a beginner-friendly project, so let’s make this project step-by-step.
Contents
Then in return statement, we have called these two components in a div. And we have passed time as a prop for <DisplayComponent/>. Okay, so this is not for all for App.js we will do some changes as we progress in the Application.
import React, {useState} from 'react';
import DisplayComponent from './Components/DisplayComponent';
import BtnComponent from './Components/BtnComponent';
import './App.css';
function App() {
const [time, setTime] = useState({ms:0, s:0, m:0, h:0});
return (
<div className="clock-holder">
<div className="main-section">
<div className="stopwatch">
<DisplayComponent time={time}/>
<BtnComponent/>
</div>
</div>
</div>
);
}
export default App;
Then we have added 3 span tags for minute, millisecond and for second. in all these span, we have added functionality to add a 0 before the actual timer if any of these time is below 10. Here we have used props to get the values from App.js component, and the changes made in App component directly reflect on here.
import React from 'react';
function DisplayComponent(props) {
const h = () => {
if(props.time.h === 0){
return '';
}else {
return <span>{(props.time.h >= 10)? props.time.h : "0"+ props.time.h}</span>;
}
}
return (
<div>
{h()}
<span>{(props.time.m >= 10)? props.time.m : "0"+ props.time.m}</span> :
<span>{(props.time.s >= 10)? props.time.s : "0"+ props.time.s}</span> :
<span>{(props.time.ms >= 10)? props.time.ms : "0"+ props.time.ms}</span>
</div>
);
}
export default DisplayComponent;
After that in start function, we have called a run() function, and we have updated status with value 1, also we have updated value of setInterv
with run function for 10ms. So each 10ms run, the function will be called. In this run function we have updated the values of hour, minutes and seconds if it hits the certain conditions. For these condition checking, we have added some temporary variable to store the values of parameters of time state
For stop(), we have just updated the status value with 2 and for reset() function we will clear out the timer and set our time status back to 0. Lastly, for resume we just called start() function to run again the timer.
const [time, setTime] = useState({ms:0, s:0, m:0, h:0});
const [interv, setInterv] = useState();
const [status, setStatus] = useState(0);
// Not started = 0
// started = 1
// stopped = 2
const start = () => {
run();
setStatus(1);
setInterv(setInterval(run, 10));
};
var updatedMs = time.ms, updatedS = time.s, updatedM = time.m, updatedH = time.h;
const run = () => {
if(updatedM === 60){
updatedH++;
updatedM = 0;
}
if(updatedS === 60){
updatedM++;
updatedS = 0;
}
if(updatedMs === 100){
updatedS++;
updatedMs = 0;
}
updatedMs++;
return setTime({ms:updatedMs, s:updatedS, m:updatedM, h:updatedH});
};
const stop = () => {
clearInterval(interv);
setStatus(2);
};
const reset = () => {
clearInterval(interv);
setStatus(0);
setTime({ms:0, s:0, m:0, h:0})
};
const resume = () => start();
return (
<div className="main-section">
<div className="clock-holder">
<div className="stopwatch">
<DisplayComponent time={time}/>
<BtnComponent status={status} resume={resume} reset={reset} stop={stop} start={start}/>
</div>
</div>
</div>
);
}
If the status value is 1 then we will add the Stop and Reset button, and we will call the props.stop and prop.reset functions. Remember that, initially status will be 0, so we will get Start button but as soon status becomes 1 then we will get Stop and Reset button and previous button (Start) won’t be shown up.
Similarly, for props.status == 2, we will add the resume and reset button with props.resume and props.reset function call.
import React from 'react';
function BtnComponent(props) {
return (
<div>
{(props.status === 0)?
<button className="stopwatch-btn stopwatch-btn-gre"
onClick={props.start}>Start</button> : ""
}
{(props.status === 1)?
<div>
<button className="stopwatch-btn stopwatch-btn-red"
onClick={props.stop}>Stop</button>
<button className="stopwatch-btn stopwatch-btn-yel"
onClick={props.reset}>Reset</button>
</div> : ""
}
{(props.status === 2)?
<div>
<button className="stopwatch-btn stopwatch-btn-gre"
onClick={props.resume}>Resume</button>
<button className="stopwatch-btn stopwatch-btn-yel"
onClick={props.reset}>Reset</button>
</div> : ""
}
</div>
);
}
export default BtnComponent;
Now our structure is pretty good, and we have added almost everything but before going to next move, let’s add some colors and customize this calculator, so this can looks like calculator atleast. I won’t go deep in CSS because CSS is actually depended on you and this is not that much hard to put color or something. So if you want same CSS then use below CSS.
App.css
body {
background:#2C3E50;
}
* {
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
.main-section {
background: transparent;
max-width: 600px;
width: 90%;
height: 500px;
margin: 30px auto;
}
.clock-holder {
width: 100%;
background: #fff;
margin: 30px auto;
position: relative;
}
.stopwatch {
padding: 60px 0px;
text-align: center;
}
.stopwatch span{
background:#00ABA9;
color: #fff;
display: inline-block;
font-family: monospace;
font-size: 22px;
padding: 20px;
border-radius: 5px;
width: 70px;
}
.stopwatch .stopwatch-btn {
background: #fff;
margin-top: 30px;
margin-left: 5px;
border: none;
padding: 12px 20px;
font-size: 16px;
text-transform: uppercase;
width: 150px;
transition: background 1s;
cursor: pointer;
}
.stopwatch .stopwatch-btn-red{
border: 2px solid #C85454;
color: #C85454;
}
.stopwatch .stopwatch-btn-yel{
border: 2px solid #FFC900;
color: #FFC900;
}
.stopwatch .stopwatch-btn-gre{
border: 2px solid #00ABA9;
color: #00ABA9;
}
.stopwatch .stopwatch-btn-red:hover {
background: #C85454;
border: 2px solid #C85454;
color: #fff;
}
.stopwatch .stopwatch-btn-yel:hover {
background: #FFC900;
border: 2px solid #FFC900;
color: #fff;
}
.stopwatch .stopwatch-btn-gre:hover {
background: #00ABA9;
border: 2px solid #00ABA9;
color: #fff;
}
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
import React, {useState} from 'react';
import DisplayComponent from './Components/DisplayComponent';
import BtnComponent from './Components/BtnComponent';
import './App.css';
function App() {
const [time, setTime] = useState({ms:0, s:0, m:0, h:0});
const [interv, setInterv] = useState();
const [status, setStatus] = useState(0);
// Not started = 0
// started = 1
// stopped = 2
const start = () => {
run();
setStatus(1);
setInterv(setInterval(run, 10));
};
var updatedMs = time.ms, updatedS = time.s, updatedM = time.m, updatedH = time.h;
const run = () => {
if(updatedM === 60){
updatedH++;
updatedM = 0;
}
if(updatedS === 60){
updatedM++;
updatedS = 0;
}
if(updatedMs === 100){
updatedS++;
updatedMs = 0;
}
updatedMs++;
return setTime({ms:updatedMs, s:updatedS, m:updatedM, h:updatedH});
};
const stop = () => {
clearInterval(interv);
setStatus(2);
};
const reset = () => {
clearInterval(interv);
setStatus(0);
setTime({ms:0, s:0, m:0, h:0})
};
const resume = () => start();
return (
<div className="main-section">
<div className="clock-holder">
<div className="stopwatch">
<DisplayComponent time={time}/>
<BtnComponent status={status} resume={resume} reset={reset} stop={stop} start={start}/>
</div>
</div>
</div>
);
}
export default App;
DisplayComponent.js
import React from 'react';
function DisplayComponent(props) {
const h = () => {
if(props.time.h === 0){
return '';
}else {
return <span>{(props.time.h >= 10)? props.time.h : "0"+ props.time.h}</span>;
}
}
return (
<div>
{h()}
<span>{(props.time.m >= 10)? props.time.m : "0"+ props.time.m}</span> :
<span>{(props.time.s >= 10)? props.time.s : "0"+ props.time.s}</span> :
<span>{(props.time.ms >= 10)? props.time.ms : "0"+ props.time.ms}</span>
</div>
);
}
export default DisplayComponent;
BtnComponent.js
import React from 'react';
function BtnComponent(props) {
return (
<div>
{(props.status === 0)?
<button className="stopwatch-btn stopwatch-btn-gre"
onClick={props.start}>Start</button> : ""
}
{(props.status === 1)?
<div>
<button className="stopwatch-btn stopwatch-btn-red"
onClick={props.stop}>Stop</button>
<button className="stopwatch-btn stopwatch-btn-yel"
onClick={props.reset}>Reset</button>
</div> : ""
}
{(props.status === 2)?
<div>
<button className="stopwatch-btn stopwatch-btn-gre"
onClick={props.resume}>Resume</button>
<button className="stopwatch-btn stopwatch-btn-yel"
onClick={props.reset}>Reset</button>
</div> : ""
}
</div>
);
}
export default BtnComponent;
body {
background:#2C3E50;
}
* {
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
.main-section {
background: transparent;
max-width: 600px;
width: 90%;
height: 500px;
margin: 30px auto;
}
.clock-holder {
width: 100%;
background: #fff;
margin: 30px auto;
position: relative;
}
.stopwatch {
padding: 60px 0px;
text-align: center;
}
.stopwatch span{
background:#00ABA9;
color: #fff;
display: inline-block;
font-family: monospace;
font-size: 22px;
padding: 20px;
border-radius: 5px;
width: 70px;
}
.stopwatch .stopwatch-btn {
background: #fff;
margin-top: 30px;
margin-left: 5px;
border: none;
padding: 12px 20px;
font-size: 16px;
text-transform: uppercase;
width: 150px;
transition: background 1s;
cursor: pointer;
}
.stopwatch .stopwatch-btn-red{
border: 2px solid #C85454;
color: #C85454;
}
.stopwatch .stopwatch-btn-yel{
border: 2px solid #FFC900;
color: #FFC900;
}
.stopwatch .stopwatch-btn-gre{
border: 2px solid #00ABA9;
color: #00ABA9;
}
.stopwatch .stopwatch-btn-red:hover {
background: #C85454;
border: 2px solid #C85454;
color: #fff;
}
.stopwatch .stopwatch-btn-yel:hover {
background: #FFC900;
border: 2px solid #FFC900;
color: #fff;
}
.stopwatch .stopwatch-btn-gre:hover {
background: #00ABA9;
border: 2px solid #00ABA9;
color: #fff;
}