Build a Calculator using React Native

Last Updated : 20 Feb, 2026

Building a simple calculator app in React Native is a great beginner-friendly project that helps you understand mobile UI development and JavaScript logic. It allows you to combine interactive components with functional programming to perform real-time calculations.

  • Design a user interface with buttons for numbers (0–9), operations (+, −, ×, ÷), and a display screen.
  • Implement functions to handle button presses and perform accurate calculations.
  • Learn core React Native concepts like components, state management, and event handling.

Here, We start implementing the React Native Calculator App step by step, from setup to task management features.

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.

1. 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.

2. For iOS users, simply scan the QR code using the Camera app.

3. 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

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

JavaScript
// Import React hooks for state and side effects
import { 
  // Hook for managing component state
  useState, 
  // Hook for performing side effects in function components
  useEffect     
} from 'react'; 
import {
  // A container that ensures content is rendered within the safe area boundaries of a device
  SafeAreaView,
  // Component for displaying text
  Text, 
  // A container for grouping other components
  View, 
  // A button-like component that responds to touch events
  TouchableOpacity, 
  // Utility for creating styles for components
  StyleSheet,       
} from 'react-native'; 

StyleSheet: Create a StyleSheet to style components like container, resultContainer, inputText, resultText, buttonsContainer, row, button, equalsButton, and buttonText.

JavaScript
// Define styles for the app
const styles = StyleSheet.create({
  container: {
    flex: 1, 
    backgroundColor: '#000', 
    justifyContent: 'space-between', 
  },
  resultContainer: {
    padding: 50, 
    alignItems: 'flex-end', 
  },
  inputText: {
    fontSize: 36, 
    color: '#AFAFAF', 
  },
  resultText: {
    fontSize: 40, 
    color: '#fff', 
    marginTop: 10,
  },
  buttonsContainer: {
    padding: 10, 
    marginBottom: 10, 
  },
  row: {
    flexDirection: 'row', 
    justifyContent: 'space-between', 
    marginVertical: 6, 
  },
  button: {
    backgroundColor: '#1c1c1c', 
    flex: 1, 
    alignItems: 'center', 
    justifyContent: 'center', 
    margin: 5, 
    height: 70, 
    borderRadius: 35, 
  },
  equalsButton: {
    backgroundColor: '#1FD660', 
    flex: 4, 
  },
  buttonText: {
    fontSize: 24, // Default font size for button text
    color: '#fff', // White text color
  },
});

buttons: Define a list of buttons for the calculator.

JavaScript
// Define the layout of calculator buttons
const buttons = [
  // First row of buttons
  ['C', '(', ')', '%'], 
  // Second row of buttons
  ['7', '8', '9', '/'], 
  // Third row of buttons
  ['4', '5', '6', '*'], 
  // Fourth row of buttons
  ['1', '2', '3', '-'], 
  // Fifth row of buttons
  ['+/-', '0', '.', '+'], 
  // Sixth row with only the equals button
  ['='], 
];

buttons UI: Use the code below to show a list of buttons. Organize the buttons with a map function and display the text for each button using a Text component. Make the buttons interactive by wrapping the Text inside a TouchableOpacity. This way, when the user taps on any button, it will call the handlePress function.

JavaScript
{/* Render the calculator buttons */}
<View style={styles.buttonsContainer}>
    {buttons.map((row, rowIndex) => (
      <View key={rowIndex} style={styles.row}>
        {row.map((btn, colIndex) => (
          <TouchableOpacity
            key={colIndex}
            style={[
              styles.button,
              btn === '=' ? styles.equalsButton : null, // Apply special style for '=' button
            ]}
            onPress={() => handlePress(btn)} // Handle button press
          >
            <Text style={[styles.buttonText, btn === '=' && { fontSize: 28 }]}>
              {btn} {/* Display the button label */}
            </Text>
          </TouchableOpacity>
        ))}
      </View>
    ))}
</View>

Input Text & Result Text: Display Input Text (Text user typing) and Result Text ( Answer to user input) using Text component wrapped with View component.

JavaScript
{/* Display the input and result */}
<View style={styles.resultContainer}>
    <Text style={styles.inputText}>{input + "  "}</Text> {/* Show the current input */}
    <Text style={styles.resultText}>{result + " "}</Text> {/* Show the calculated result */}
</View>

handlePress: Function to make every button functional.

JavaScript
const handlePress = (btn) => {
    if (btn === 'C') {
        // Clear input and result when 'C' is pressed
        setInput('');
        setResult('');
    } else if (btn === '=') {
        // Do nothing since the result is calculated automatically
    } else if (btn === '+/-') {
        // Toggle the sign of the input
        if (input.startsWith('-')) setInput(input.substring(1));
        else setInput('-' + input);
    } else {
        // Append the button value to the input
        setInput((prev) => prev + btn);
    }
};

- useState: Used to manage the state of input and result.

JavaScript
// State to store the current input
const [input, setInput] = useState('');
// State to store the calculated result
const [result, setResult] = useState('');

useEffect: Used to calculate the result whenever the input changes.

JavaScript
// Effect to calculate the result whenever the input changes
useEffect(() => {
    try {
        if (input) {
            // Replace custom operators with JavaScript-compatible ones
            let finalInput = input.replace(/×/g, '*').replace(/÷/g, '/');
            // Evaluate the expression and update the result
            const evalResult = eval(finalInput);
            setResult(evalResult.toString());
        } else {
            // Clear the result if input is empty
            setResult('');
        }
    } catch (e) {
        // Handle invalid expressions gracefully
        setResult('');
    }
}, [input]); // Dependency array ensures this runs when `input` changes

Now, wrap the buttons UI, input Text & result Text components with a SafeAreaView component and return from the App component. Also, ensure to export the App.

Complete Source Code

App.js:

App.js
import { 
  useState,     // Hook for managing component state
  useEffect     // Hook for performing side effects in function components
} from 'react'; // Import React hooks for state and side effects
import {
  SafeAreaView,     // A container that ensures content is rendered within the safe area boundaries of a device
  Text,             // Component for displaying text
  View,             // A container for grouping other components
  TouchableOpacity, // A button-like component that responds to touch events
  StyleSheet,       // Utility for creating styles for components
} from 'react-native'; // Import React Native components for UI


// Define the layout of calculator buttons
const buttons = [
  ['C', '(', ')', '%'], // First row of buttons
  ['7', '8', '9', '/'], // Second row of buttons
  ['4', '5', '6', '*'], // Third row of buttons
  ['1', '2', '3', '-'], // Fourth row of buttons
  ['+/-', '0', '.', '+'], // Fifth row of buttons
  ['='], // Sixth row with only the equals button
];

const App = () => {
  // State to store the current input
  const [input, setInput] = useState('');
  // State to store the calculated result
  const [result, setResult] = useState('');

  // Effect to calculate the result whenever the input changes
  useEffect(() => {
    try {
      if (input) {
        // Replace custom operators with JavaScript-compatible ones
        let finalInput = input.replace(/×/g, '*').replace(/÷/g, '/');
        // Evaluate the expression and update the result
        const evalResult = eval(finalInput);
        setResult(evalResult.toString());
      } else {
        // Clear the result if input is empty
        setResult('');
      }
    } catch (e) {
      // Handle invalid expressions gracefully
      setResult('');
    }
  }, [input]); // Dependency array ensures this runs when `input` changes

  // Function to handle button presses
  const handlePress = (btn) => {
    if (btn === 'C') {
      // Clear input and result when 'C' is pressed
      setInput('');
      setResult('');
    } else if (btn === '=') {
      // Do nothing since the result is calculated automatically
    } else if (btn === '+/-') {
      // Toggle the sign of the input
      if (input.startsWith('-')) setInput(input.substring(1));
      else setInput('-' + input);
    } else {
      // Append the button value to the input
      setInput((prev) => prev + btn);
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      {/* Display the input and result */}
      <View style={styles.resultContainer}>
        <Text style={styles.inputText}>{input + "  "}</Text> {/* Show the current input */}
        <Text style={styles.resultText}>{result + " "}</Text> {/* Show the calculated result */}
      </View>

      {/* Render the calculator buttons */}
      <View style={styles.buttonsContainer}>
        {buttons.map((row, rowIndex) => (
          <View key={rowIndex} style={styles.row}>
            {row.map((btn, colIndex) => (
              <TouchableOpacity
                key={colIndex}
                style={[
                  styles.button,
                  btn === '=' ? styles.equalsButton : null, // Apply special style for '=' button
                ]}
                onPress={() => handlePress(btn)} // Handle button press
              >
                <Text style={[styles.buttonText, btn === '=' && { fontSize: 28 }]}>
                  {btn} {/* Display the button label */}
                </Text>
              </TouchableOpacity>
            ))}
          </View>
        ))}
      </View>
    </SafeAreaView>
  );
};

// Define styles for the app
const styles = StyleSheet.create({
  container: {
    flex: 1, // Take up the full screen
    backgroundColor: '#000', // Black background
    justifyContent: 'space-between', // Space out elements vertically
  },
  resultContainer: {
    padding: 50, // Add padding around the result area
    alignItems: 'flex-end', // Align text to the right
  },
  inputText: {
    fontSize: 36, // Large font for input
    color: '#AFAFAF', // Light gray color
  },
  resultText: {
    fontSize: 40, // Larger font for result
    color: '#fff', // White color
    marginTop: 10, // Add spacing above the result
  },
  buttonsContainer: {
    padding: 10, // Add padding around the buttons
    marginBottom: 10, // Add margin at the bottom
  },
  row: {
    flexDirection: 'row', // Arrange buttons in a row
    justifyContent: 'space-between', // Space out buttons evenly
    marginVertical: 6, // Add vertical spacing between rows
  },
  button: {
    backgroundColor: '#1c1c1c', // Dark gray background for buttons
    flex: 1, // Buttons take equal space
    alignItems: 'center', // Center button text horizontally
    justifyContent: 'center', // Center button text vertically
    margin: 5, // Add spacing between buttons
    height: 70, // Set button height
    borderRadius: 35, // Make buttons circular
  },
  equalsButton: {
    backgroundColor: '#1FD660', // Green background for '=' button
    flex: 4, // Make '=' button wider
  },
  buttonText: {
    fontSize: 24, // Default font size for button text
    color: '#fff', // White text color
  },
});

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

Output:

Comment

Explore