This blog was originally posted on Hashnode.
Hey there! It has been a while since I blogged, but I want to become more active, especially as I begin to study more for interviews. I recently had a practice interview with PRAMP, where I signed up for a front-end interview that focused on building a flip counter. The goal is to:
**Flip Counter - Build a flip counter that counts a minute (0-59) iteratively.If you can, try and minimize the creation of new DOM elements in runtime, by reusing the same elements."
I wanted to use React since that is what I use the most. Building a counter is simple, there is an example given in the React documentation:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
I started by creating a variable named count that I would keep track of the state, then I used the React.useEffect
hook to check if count is less than 59. If it is, it would continue to increment, else it should stop. In addition, I added a setTimeout
so that it would increment every second, just like a timer. Then I returned/rendered the {count}
variable in the app.
import React from 'react';
export function App(props) {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
if(count <= 59)
setTimeout(() => {
setCount(count + 1)
}, "1000")
}
})
return (
<div className='App'>
<h1> Counter </h1>
<span className="counter">
{count}
</span>
</div>
);
}
This worked, but there was one problem, I was having a hard time with styling because the count
is considered one variable. While I am sure there is a way to abstract the numbers, I decided to take the approach of creating two more variables to keep track of the numbers.
import React from "react";
import "./styles.css";
export default function App() {
const [count, setCount] = React.useState(0);
const [first, setFirst] = React.useState("");
const [second, setSecond] = React.useState("");
React.useEffect(() => {
if (count <= 59) {
setTimeout(() => {
setCount(count + 1);
}, "1000");
if (count < 10) {
setSecond(count);
} else {
const getFirstNumber = count.toString()[0];
const getSecondNumber = count.toString()[1];
console.log(typeof getFirstNumber);
setSecond(getSecondNumber);
setFirst(getFirstNumber);
}
}
}, [count]);
return (
<div className="App">
<h1> Counter </h1>
<div className="counter">
<span>{first}</span>
<span>{second}</span>
</div>
</div>
);
}
Then I added the CSS for each span!
.App {
font-family: sans-serif;
text-align: center;
}
.counter {
display: flex;
justify-content: center;
align-content: space-between;
gap: 10px 20px;
font-size: 200px;
}
.counter span:nth-of-type(1) {
background-color: grey;
border-radius: 30px;
}
.counter span:nth-of-type(2) {
background-color: grey;
border-radius: 30px;
}
However, after further thought, I realized this would not work if the number was 3 digits long so maybe it is best if I use an array and iterate over it!
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [count, setCount] = React.useState(0);
const [numArr, setNumArr] = React.useState([]);
const [first, setFirst] = React.useState("0");
const [second, setSecond] = React.useState("");
React.useEffect(() => {
if (count <= 59) {
setTimeout(() => {
setCount(count + 1);
}, "1000");
if (count < 10) {
setSecond(count);
} else {
let num = count.toString().split("");
console.log(num);
setNumArr(num);
}
}
}, [count]);
return (
<div className="App">
<h1> Counter </h1>
<div className="counter">
{count < 10 ? (
<>
<span>{first}</span>
<span>{second}</span>
</>
) : (
<>
{numArr.map((num) => (
<>
<span>{num[0]}</span>
<span>{num[1]}</span>
</>
))}
</>
)}
</div>
</div>
);
}
Then I updated the CSS. I am not a pro at CSS yet, so I am not sure how to add the span:nth-of-type
to all future spans, but it would be helpful, for now, I just added the.counter span:nth-of-type(3)
to the css.
.App {
font-family: sans-serif;
text-align: center;
}
.counter {
display: flex;
justify-content: center;
align-content: space-between;
gap: 10px 20px;
font-size: 200px;
}
.counter span:nth-of-type(1) {
background-color: grey;
border-radius: 30px;
}
.counter span:nth-of-type(2) {
background-color: grey;
border-radius: 30px;
}
.counter span:nth-of-type(3) {
background-color: grey;
border-radius: 30px;
}
Once, I got that working I reread the question and realized that the question ask that I build a flip counter that counts a minute (0-59) iteratively! So, I added code that checks to see if count <= 59
and if it is, it will update setCount(0)
to zero, updating the state allows the component to rerender, since it is watching the count state in the React.useEffect. It allows the app to count from (0-59) iteratively!
import React from "react";
import "./styles.css";
export default function App() {
const [count, setCount] = React.useState(0);
const [numArr, setNumArr] = React.useState([]);
const [first, setFirst] = React.useState("0");
const [second, setSecond] = React.useState("");
React.useEffect(() => {
if (count <= 59) {
setTimeout(() => {
setCount(count + 1);
}, "1000");
if (count < 10) {
setSecond(count);
} else {
let num = count.toString().split("");
console.log(num);
setNumArr(num);
}
}
}, [count]);
return (
<div className="App">
<h1> Counter </h1>
{count <= 59 ? (
<div className="counter">
{count < 10 ? (
<>
<span>{first}</span>
<span>{second}</span>
</>
) : (
<>
{numArr.map((num) => (
<>
<span>{num[0]}</span>
<span>{num[1]}</span>
</>
))}
</>
)}
</div>
) : (
setCount(0)
)}
</div>
);
}
This appeared to work, I did not add any animations, but I was able to create the task at hand. Let me know if you have any advice on how to make the code better.
Thank you for reading!
Sincerely,
Brittany
As always, a song!
Top comments (1)
Nice work! Any chance you'd consider linking to a deployed version e.g. on Github? This is one of the top search results I found as I am preparing to assess a Pramp interview!