Countdown functionality can be seen everywhere on websites and applications, used for various occasions such as online exams, waiting before an event starts, limited-time promotions, etc. If you are a React beginner, you might think that implementing such functionality requires writing complex code. But in fact, React's design philosophy and powerful Hooks make it extremely simple.
This article will guide you step by step to implement a simple 60-second countdown timer, helping you understand React's state management and handling of side effects, as well as how to simplify code using React Hooks.
Why do we need a countdown timer?#
A countdown timer can improve user experience by providing clear time feedback. Whether it's completing a task within a specific time or waiting for a certain event to occur, a countdown timer can provide clear visual indication to help users react.
Getting started: Creating a React application#
First, make sure you have Node.js and npm installed, and create a new React application using the following command:
npx create-react-app countdown-timer
Navigate into the project and start the application:
cd countdown-timer
npm start
Thinking about the countdown logic#
The core of implementing the countdown functionality lies in two points:
State management: Continuous updating of the countdown time is a typical state management problem.
Handling side effects: Updating time relies on JavaScript timers, which is a side effect.
In React, the useState
hook is used for state management, and the useEffect
hook is used for handling side effects.
Writing the countdown component
In the src
folder of your project, create a file named Countdown.js
and write the following code:
// src/Countdown.js
import React, { useState, useEffect } from 'react';
const Countdown = () => {
// Use useState to manage the countdown time
const [seconds, setSeconds] = useState(60);
// Use useEffect to handle the countdown logic
useEffect(() => {
if (seconds > 0) {
// Only set the timer when seconds is greater than 0
const timerId = setTimeout(() => setSeconds(seconds - 1), 1000);
// Clean up the timer
return () => clearTimeout(timerId);
}
}, [seconds]);// Depends on seconds, will reset timeout whenever seconds changes
return <div>Remaining time: {seconds} seconds</div>;
};
export default Countdown;
Key points explained#
useState hook: Used to declare the state seconds
of the countdown and initialize it to 60. setSeconds
is a function used to update the value of seconds
.
useEffect hook: Handles side effects, in this case, the timer. useEffect
takes a function that will be executed after the component is rendered on the screen. This function will be re-executed whenever seconds
changes.
In the callback function of useEffect
, we use setTimeout
to set a timer that calls setSeconds
every second to decrease the value of seconds
.
Note that we return a function in useEffect
, which will be called before the component is unmounted or before useEffect
is re-executed. This function is used to clean up the previous timer, avoiding memory leaks.
Using the Countdown component#
In src/App.js
, import and use the Countdown
component:
// src/App.js
import React from 'react';
import './App.css';
import Countdown from './Countdown';
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Countdown Timer</h1>
<Countdown />
</header>
</div>
);
}
export default App;
Now, start the application and you should see a countdown timer counting down from 60 on the page.
Summary#
Through this simple example, we have learned how to use the useState
and useEffect
hooks in React to manage state and handle side effects. This demonstrates React's declarative programming feature - you only need to tell React what result you want, and React takes care of implementing it.
Now that you know how to create a simple countdown timer, you can apply this knowledge to more complex functionalities or try adding additional features to the countdown timer, such as a reset button or custom time.
Initially, my idea was to use
setTimeOut
inuseEffect
and then use a for loop to implement it. Although it can also work, there is a problem here. Do you know why? 🤭