Open In App

Create a Stop Watch using React Native

Last Updated : 24 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Stopwatches serve as vital tools for accurately measuring time­ intervals. By the capabilities of React Native, we can effortle­ssly develop a versatile­ stopwatch application compatible with both iOS and Android devices. In this article, we­ will guide you through the step-by-step process of creating a straightforward stopwatch app using React Native­.

Create-a--StopWatch-Using-React-Native_


To give you a better idea of what we’re going to create, let’s watch a demo video.

Demo Video

Prerequisites:

Step-by-Step Implementation

Step 1: Create a React Native Project

Now, create a project with the following command.

npx create-expo-app app-name --template

Note: Replace the app-name with your app name for example : react-native-demo-app

Next, you might be asked to choose a template. Select one based on your preference as shown in the image below. I am selecting the blank template because it will generate a minimal app that is as clean as an empty canvas in JavaScript.


It completes the project creation and displays a message: "Your Project is ready!" as shown in the image below.


Now go into your project folder, i.e., react-native-demo

cd app-name

Project Structure:

Step 2: Run  Application

Start the server by using the following command.

npx expo start

Then, the application will display a QR code.

  • For the Android users,
    • For the Android Emulator, press "a" as mentioned in the image below.
    • For the Physical Device, download the "Expo Go" app from the Play Store. Open the app, and you will see a button labeled "Scan QR Code." Click that button and scan the QR code; it will automatically build the Android app on your device.
  • For iOS users, simply scan the QR code using the Camera app.
  • If you're using a web browser, it will provide a local host link that you can use as mentioned in the image below.

Step 3: Start Coding

Approach:

In this approach, we create a stopwatch with start, pause, resume, and reset buttons. It utilizes state and refs to manage time and running status, updating time every second through intervals.

Example: The use­State hook is utilized for managing the state­ of both the time (repre­senting current elapse­d time) and running variables in the stopwatch. On the­ other hand, the useRe­f hook is employed to store re­ferences to both the­ interval and start time, ensuring pre­cise calculations of time. The functions startStopwatch, pause­Stopwatch, resetStopwatch, and resume­Stopwatch are responsible for handling the­ behavior of the stopwatch. They e­ffectively manage inte­rval timers, update the e­lapsed time, and control their running state base­d on user actions. The UI compone­nts in the JSX are rende­red by the return state­ment. It showcases various ele­ments like the he­ader, subheader, curre­nt elapsed time, and buttons that change­ based on the stopwatch's state. To e­nsure consistent and organized styling, the Style­Sheet.create­ function is used to define style­s.

Let's Start!.

- Import libraries: Import required libraries at the top of the file.

JavaScript
// Import necessary hooks and components from React and React Native
import { useState, useRef } from 'react';

import {
    View,            // Container component for layout
    Text,            // Component for displaying text
    StyleSheet,      // For creating styles
    TouchableOpacity // For creating touchable buttons
} from 'react-native';


- StyleSheet: Create a StyleSheet to style components like container, header, subHeader, etc.

JavaScript
// Styles for the components
const styles = StyleSheet.create({
    container: {
        flex: 1,                    // Take up full screen
        justifyContent: 'center',   // Center vertically
        alignItems: 'center',       // Center horizontally
    },
    header: {
        fontSize: 30,               // Large font size
        color: "green",             // Green color
        marginBottom: 10,           // Space below
    },
    subHeader: {
        fontSize: 18,               // Medium font size
        marginBottom: 10,           // Space below
        color: "blue",              // Blue color
    },
    timeText: {
        fontSize: 48,               // Very large font for time
    },
    buttonContainer: {
        flexDirection: 'row',       // Arrange buttons in a row
        marginTop: 20,              // Space above
    },
    button: {
        paddingVertical: 10,        // Vertical padding
        paddingHorizontal: 20,      // Horizontal padding
        borderRadius: 5,            // Rounded corners
    },
    startButton: {
        backgroundColor: '#2ecc71', // Green background
        marginRight: 10,            // Space to the right
    },
    resetButton: {
        backgroundColor: '#e74c3c', // Red background
        marginRight: 10,            // Space to the right
    },
    pauseButton: {
        backgroundColor: '#f39c12', // Orange background
    },
    resumeButton: {
        backgroundColor: '#3498db', // Blue background
    },
    buttonText: {
        color: 'white',             // White text
        fontSize: 16,               // Medium font size
        textAlign: "center",
        fontFamily: ""

    },
    
});


Develop UI

- Title & Subtitle: Here is the code to display the title and subtitle of the app using a Text component, which conveys who is providing the app (for ex: "Geeksforgeeks") and its purpose (for ex: "Stop Watch In Native").

JavaScript
{/* App Title */}
<Text style={styles.header}>
    Geeksforgeeks
</Text>
{/* Sub-title */}
<Text style={styles.subHeader}>
    Stop Watch In Native
</Text>


- Display time: Display time by calling the "time" state variable in Text component and the time will update by calling the setTime useState function.

JavaScript
// State to keep track of elapsed time in seconds
const [time, setTime] = useState(0);

// Below Text component is placed below the Title and Sub-Tile of the app
{/* Display elapsed time */}
<Text style={styles.timeText}>{time}s</Text>


- Buttons: We have four buttons: Start, Reset, Resume, and Pause. Each button does exactly what its name suggests. They are designed using a Text component wrapped in a TouchableOpacity component to make them work as buttons. All the buttons are grouped in a View component.

The Pause button only shows up when the timer is running, which is indicated by a "running" state variable. When "running" is true, only the Pause button is visible. When "running" is false, the Start, Reset, and Resume buttons are shown. Each button triggers a specific method: startStopwatch, resetStopwatch, resumeStopwatch, and pauseStopwatch.

JavaScript
// State to keep track of whether the stopwatch is running
const [running, setRunning] = useState(false);

// Below Code is placed after the Displat time
{/* Button container */}
<View style={styles.buttonContainer}>
    {/* If stopwatch is running, show Pause button */}
    {running ? (
        <TouchableOpacity
            style={[styles.button, styles.pauseButton]}
            onPress={pauseStopwatch}
        >
            <Text style={styles.buttonText}>Pause</Text>
        </TouchableOpacity>
    ) : (
        // If not running, show Start and Reset buttons
        <>
            <TouchableOpacity
                style={[styles.button, styles.startButton]}
                onPress={startStopwatch}
            >
                <Text style={styles.buttonText}>Start</Text>
            </TouchableOpacity>
            <TouchableOpacity
                style={[styles.button, styles.resetButton]}
                onPress={resetStopwatch}
            >
                <Text style={styles.buttonText}>
                    Reset
                </Text>
            </TouchableOpacity>
        </>
    )}
    {/* If not running, show Resume button */}
    {!running && (
        <TouchableOpacity
            style={[styles.button, styles.resumeButton]}
            onPress={resumeStopwatch}
        >
            <Text style={styles.buttonText}>Resume</Text>
        </TouchableOpacity>
    )}
</View>


- Methods: Here we have 4 methods: startStopwatch, resetStopwatch, resumeStopwatch, and pauseStopwatch, providing functionality as their name suggests with the help of intervalRef and startTimeRef useState.

JavaScript
// Ref to store the interval ID for clearing it later
const intervalRef = useRef(null);

// Ref to store the start time (in ms) for accurate time calculation
const startTimeRef = useRef(0);


// All Fnction placed inside the App Component
// Function to start the stopwatch
const startStopwatch = () => {
    // Set the start time, accounting for any previously elapsed time
    startTimeRef.current = Date.now() - time * 1000;
    // Start interval to update time every second
    intervalRef.current = setInterval(() => {
        // Update time state with elapsed seconds
        setTime(Math.floor((Date.now() - startTimeRef.current) / 1000));
    }, 1000);
    // Set running state to true
    setRunning(true);
};

// Function to pause the stopwatch
const pauseStopwatch = () => {
    // Clear the interval to stop updating time
    clearInterval(intervalRef.current);
    // Set running state to false
    setRunning(false);
};

// Function to reset the stopwatch
const resetStopwatch = () => {
    // Clear the interval
    clearInterval(intervalRef.current);
    // Reset time to 0
    setTime(0);
    // Set running state to false
    setRunning(false);
};

// Function to resume the stopwatch from paused state
const resumeStopwatch = () => {
    // Set the start time to account for already elapsed time
    startTimeRef.current = Date.now() - time * 1000;
    // Start interval to update time every second
    intervalRef.current = setInterval(() => {
        // Update time state with elapsed seconds
        setTime(Math.floor((Date.now() - startTimeRef.current) / 1000));
    }, 1000);
    // Set running state to true
    setRunning(true);
};


Now, wrap all design code with a View component, return it from the App component, and place all methods and useStates within the App component. Ensure to export the App.

Complete Source Code

App.js:

App.js
// Import necessary hooks and components from React and React Native
import { useState, useRef } from 'react';
import {
    View,            // Container component for layout
    Text,            // Component for displaying text
    StyleSheet,      // For creating styles
    TouchableOpacity // For creating touchable buttons
} from 'react-native';

// Main App component
const App = () => {

    // State to keep track of elapsed time in seconds
    const [time, setTime] = useState(0);

    // State to keep track of whether the stopwatch is running
    const [running, setRunning] = useState(false);

    // Ref to store the interval ID for clearing it later
    const intervalRef = useRef(null);

    // Ref to store the start time (in ms) for accurate time calculation
    const startTimeRef = useRef(0);

    // Function to start the stopwatch
    const startStopwatch = () => {
        
        // Set the start time, accounting for any previously elapsed time
        startTimeRef.current = Date.now() - time * 1000;
        
        // Start interval to update time every second
        intervalRef.current = setInterval(() => {
            
            // Update time state with elapsed seconds
            setTime(Math.floor((Date.now() - startTimeRef.current) / 1000));
        }, 1000);
        
        // Set running state to true
        setRunning(true);
    };

    // Function to pause the stopwatch
    const pauseStopwatch = () => {
        
        // Clear the interval to stop updating time
        clearInterval(intervalRef.current);
        
        // Set running state to false
        setRunning(false);
    };

    // Function to reset the stopwatch
    const resetStopwatch = () => {
        
        // Clear the interval
        clearInterval(intervalRef.current);
        
        // Reset time to 0
        setTime(0);
        
        // Set running state to false
        setRunning(false);
    };

    // Function to resume the stopwatch from paused state
    const resumeStopwatch = () => {
        
        // Set the start time to account for already elapsed time
        startTimeRef.current = Date.now() - time * 1000;
        
        // Start interval to update time every second
        intervalRef.current = setInterval(() => {
            
            // Update time state with elapsed seconds
            setTime(Math.floor((Date.now() - startTimeRef.current) / 1000));
        }, 1000);
        
        // Set running state to true
        setRunning(true);
    };

    // Render UI
    return (
        <View style={styles.container}>
            {/* App Title */}
            <Text style={styles.header}>
                Geeksforgeeks
            </Text>
            
            {/* Sub-title */}
            <Text style={styles.subHeader}>
                Stop Watch In Native
            </Text>
            
            {/* Display elapsed time */}
            <Text style={styles.timeText}>{time}s</Text>
            
            {/* Button container */}
            <View style={styles.buttonContainer}>
                
                {/* If stopwatch is running, show Pause button */}
                {running ? (
                    <TouchableOpacity
                        style={[styles.button, styles.pauseButton]}
                        onPress={pauseStopwatch}
                    >
                        <Text style={styles.buttonText}>Pause</Text>
                    </TouchableOpacity>
                ) : (
                
                    // If not running, show Start and Reset buttons
                    <>
                        <TouchableOpacity
                            style={[styles.button, styles.startButton]}
                            onPress={startStopwatch}
                        >
                            <Text style={styles.buttonText}>Start</Text>
                        </TouchableOpacity>
                        <TouchableOpacity
                            style={[styles.button, styles.resetButton]}
                            onPress={resetStopwatch}
                        >
                            <Text style={styles.buttonText}>
                                Reset
                            </Text>
                        </TouchableOpacity>
                    </>
                )}
                
                {/* If not running, show Resume button */}
                {!running && (
                    <TouchableOpacity
                        style={[styles.button, styles.resumeButton]}
                        onPress={resumeStopwatch}
                    >
                        <Text style={styles.buttonText}>Resume</Text>
                    </TouchableOpacity>
                )}
            </View>
        </View>
    );
};

// Styles for the components
const styles = StyleSheet.create({
    container: {
        flex: 1,                    // Take up full screen
        justifyContent: 'center',   // Center vertically
        alignItems: 'center',       // Center horizontally
    },
    header: {
        fontSize: 30,               // Large font size
        color: "green",             // Green color
        marginBottom: 10,           // Space below
    },
    subHeader: {
        fontSize: 18,               // Medium font size
        marginBottom: 10,           // Space below
        color: "blue",              // Blue color
    },
    timeText: {
        fontSize: 48,               // Very large font for time
    },
    buttonContainer: {
        flexDirection: 'row',       // Arrange buttons in a row
        marginTop: 20,              // Space above
    },
    button: {
        paddingVertical: 10,        // Vertical padding
        paddingHorizontal: 20,      // Horizontal padding
        borderRadius: 5,            // Rounded corners
    },
    startButton: {
        backgroundColor: '#2ecc71', // Green background
        marginRight: 10,            // Space to the right
    },
    resetButton: {
        backgroundColor: '#e74c3c', // Red background
        marginRight: 10,            // Space to the right
    },
    pauseButton: {
        backgroundColor: '#f39c12', // Orange background
    },
    resumeButton: {
        backgroundColor: '#3498db', // Blue background
    },
    buttonText: {
        color: 'white',             // White text
        fontSize: 16,               // Medium font size
        textAlign: "center",
        fontFamily: ""

    },

});

// Export the App component as default
export default App;

Output:


Next Article

Similar Reads