BMI Calculator App in React Native
BMI Calculator App
~10 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
The BMI calculator is the classic "form with a calculation" app – a good example of numeric input validation, derived values, and a visual result display with category colors.
1. Description
Body Mass Index: weight (kg) / height (m)². The app takes height (in cm, converted internally) and weight as text input, converts them to numbers, computes the BMI, and assigns it to one of four WHO categories with a matching color.
2. Short example
const bmi = weightKg / (heightM * heightM);
// e.g. 70 / (1.75 * 1.75) = 22.863. Complete project: a BMI calculator with categories
npx create-expo-app bmi-calculator-app
cd bmi-calculator-appexport function calculateBmi(heightCm, weightKg) {
const heightM = heightCm / 100;
return weightKg / (heightM * heightM);
}
export function bmiCategory(bmi) {
if (bmi < 18.5) return { label: 'Underweight', color: '#3b82f6' };
if (bmi < 25) return { label: 'Normal weight', color: '#16a34a' };
if (bmi < 30) return { label: 'Overweight', color: '#f59e0b' };
return { label: 'Obesity', color: '#dc2626' };
}import { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet } from 'react-native';
import { calculateBmi, bmiCategory } from './utils/bmi';
export default function App() {
const [height, setHeight] = useState('175');
const [weight, setWeight] = useState('70');
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
function calculate() {
const heightNumber = parseFloat(height.replace(',', '.'));
const weightNumber = parseFloat(weight.replace(',', '.'));
if (!heightNumber || !weightNumber || heightNumber <= 0 || weightNumber <= 0) {
setError('Please enter valid, positive numbers.');
setResult(null);
return;
}
setError(null);
const bmi = calculateBmi(heightNumber, weightNumber);
setResult({ bmi, category: bmiCategory(bmi) });
}
return (
<View style={styles.container}>
<Text style={styles.title}>BMI Calculator</Text>
<Text style={styles.label}>Height (cm)</Text>
<TextInput
style={styles.input}
value={height}
onChangeText={setHeight}
keyboardType="decimal-pad"
/>
<Text style={styles.label}>Weight (kg)</Text>
<TextInput
style={styles.input}
value={weight}
onChangeText={setWeight}
keyboardType="decimal-pad"
/>
<TouchableOpacity style={styles.button} onPress={calculate}>
<Text style={styles.buttonText}>Calculate BMI</Text>
</TouchableOpacity>
{error && <Text style={styles.errorText}>{error}</Text>}
{result && (
<View style={[styles.resultBox, { borderColor: result.category.color }]}>
<Text style={[styles.bmiValue, { color: result.category.color }]}>
{result.bmi.toFixed(1)}
</Text>
<Text style={[styles.categoryText, { color: result.category.color }]}>
{result.category.label}
</Text>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, paddingTop: 80, paddingHorizontal: 24 },
title: { fontSize: 24, fontWeight: 'bold', marginBottom: 24, textAlign: 'center' },
label: { color: '#6b7280', marginBottom: 4 },
input: { borderWidth: 1, borderColor: '#d1d5db', borderRadius: 8, padding: 10, marginBottom: 16, fontSize: 16 },
button: { backgroundColor: '#2563eb', padding: 14, borderRadius: 8, alignItems: 'center' },
buttonText: { color: 'white', fontWeight: 'bold', fontSize: 16 },
errorText: { color: '#dc2626', marginTop: 12, textAlign: 'center' },
resultBox: { marginTop: 24, borderWidth: 2, borderRadius: 12, padding: 24, alignItems: 'center' },
bmiValue: { fontSize: 36, fontWeight: 'bold' },
categoryText: { fontSize: 16, marginTop: 4 },
});4. Explanation
height.replace(',', '.')– accounts for users who often type a comma instead of a period as the decimal separator; without this normalization,parseFloat('1,75')would only return1.keyboardType="decimal-pad"shows a numeric keyboard WITH a decimal point – more user-friendly than the default keyboard for purely numeric input fields.- The validation (
!heightNumber || heightNumber <= 0) checks SIMULTANEOUSLY forNaN(on invalid input like "abc",parseFloatreturnsNaN, which is falsy) AND for nonsensical negative/zero values in a single expression. bmiCategory()is deliberately extracted as a PURE function (no component state, no side effects) – easily testable in isolation and reusable, should the app later be extended with a history view.