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 hit the start button, a 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.
Then in a 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 make 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 added 3 span tags for a 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 times is below 10. Here we have used props to get the values from the App.js component, and the changes made in the App component are directly reflected 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 the start function, we called a run() function, and we updated the status with value 1, also we updated the value of setInterv with a run function for 10ms. So each 10ms run, the function will be called. In this run function, we have updated the values of hours, minutes, and seconds if it hits certain conditions. For these condition checking, we have added some temporary variables to store the values of parameters of the time state
For stop(), we have just updated the status value with 2 and for the reset() function we will clear out the timer and set our time status back to 0. Lastly, for the resume, we just called the 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 the Start button but as soon status becomes 1 then we will get the Stop and Reset button and the previous button (Start) won’t show 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 the next move, let’s add some colors and customize this calculator, so this can look like a calculator at least. I won’t go deep in CSS because CSS is actually dependent on you and this is not that hard to put color or something. So if you want the same CSS then use the 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;
}
[…] Then in return statement, we have called these two components in a div. And we have passed time as a prop for . Okay, so this is not for all for App.js we will do some changes as we progress in the Application. Read More […]