Menu

Developing the UnitConverter Component

Developing the UnitConverter Component

This Unit Converter app combines multiple React states, functions, and dynamic UI logic to provide instant unit conversion. The app starts with tabs (Length, Weight, Temperature), where the user selects a category, and, based on that selection, the unitData object provides different conversion options via radio buttons.

After selecting a conversion type, the user can enter values in either of the two input fields, which are fully controlled using React state (value1, value2).

When the user types, the event handlers (handleInput1, handleInput2) get triggered and call the main convert function, which applies the correct mathematical formula based on the selected unit pair and direction, then instantly updates the second input field.

The getUnits function dynamically updates the input placeholders, such as km, m, °C, etc., based on the selected conversion.

The app also includes a swap button that toggles the reverse state and reorders the input fields visually without affecting the conversion logic. Additionally, whenever the user changes the tab or conversion type, both inputs are cleared to ensure fresh calculations.

File Path: UnitConverter\src\components\UnitConverter.jsx

import React, { useState } from 'react'


const UnitConverter = () => {


    const [activeTab, setActiveTab] = useState('Length')


    const [conversion, setConversion] = useState('km-m')
    const [reverse, setReverse] = useState(false)


    const [value1, setValue1] = useState('')
    const [value2, setValue2] = useState('')




    const unitData = {
        Length: [
            { label: 'Kilometer ↔ Meter', key: 'km-m' },
            { label: 'Inch ↔ Centimeter', key: 'inch-cm' },
            { label: 'Mile ↔ Kilometer', key: 'mile-km' },
            { label: 'Centimeter ↔ Meter', key: 'cm-m' },
        ],
        Weight: [
            { label: 'Kilogram ↔ Gram', key: 'kg-g' },
            { label: 'Pound ↔ Kilogram', key: 'lb-kg' },
            { label: 'Ounce ↔ Gram', key: 'oz-g' },
        ],
        Temperature: [
            { label: 'Celsius ↔ Fahrenheit', key: 'c-f' },
            { label: 'Celsius ↔ Kelvin', key: 'c-k' },
            { label: 'Fahrenheit ↔ Kelvin', key: 'f-k' },
        ]
    }




    const getUnits = (key) => {
        const map = {
            'km-m': ['km', 'm'],
            'inch-cm': ['inch', 'cm'],
            'mile-km': ['mile', 'km'],
            'cm-m': ['cm', 'm'],


            'kg-g': ['kg', 'g'],
            'lb-kg': ['lb', 'kg'],
            'oz-g': ['oz', 'g'],


            'c-f': ['°C', '°F'],
            'c-k': ['°C', 'K'],
            'f-k': ['°F', 'K'],
        }
        return map[key] || ['', '']
    }


    const convert = (type, value, direction) => {
        if (!value) return ''


        const val = parseFloat(value)


        switch (type) {


            // ---------------- LENGTH ----------------
            case 'km-m':
                return direction === 'to'
                    ? val * 1000
                    : val / 1000


            case 'inch-cm':
                return direction === 'to'
                    ? val * 2.54
                    : val / 2.54


            case 'mile-km':
                return direction === 'to'
                    ? val * 1.60934
                    : val / 1.60934


            case 'cm-m':
                return direction === 'to'
                    ? val / 100
                    : val * 100




            // ---------------- WEIGHT ----------------
            case 'kg-g':
                return direction === 'to'
                    ? val * 1000
                    : val / 1000


            case 'lb-kg':
                return direction === 'to'
                    ? val * 0.453592
                    : val / 0.453592


            case 'oz-g':
                return direction === 'to'
                    ? val * 28.3495
                    : val / 28.3495




            // ---------------- TEMPERATURE ----------------
            case 'c-f':
                return direction === 'to'
                    ? (val * 9) / 5 + 32
                    : (val - 32) * 5 / 9


            case 'c-k':
                return direction === 'to'
                    ? val + 273.15
                    : val - 273.15


            case 'f-k':
                return direction === 'to'
                    ? (val - 32) * 5 / 9 + 273.15
                    : (val - 273.15) * 9 / 5 + 32


            default:
                return ''
        }
    }






    const handleInput1 = (e) => {
        const val = e.target.value
        setValue1(val)


        const result = convert(conversion, val, 'to')
        setValue2(result)
    }


    const handleInput2 = (e) => {
        const val = e.target.value
        setValue2(val)


        const result = convert(conversion, val, 'from')
        setValue1(result)
    }


    const units = getUnits(conversion)






    const inputs = [
        {
            value: value1,
            onChange: handleInput1,
            placeholder: `Enter ${units[0]}`
        },
        {
            value: value2,
            onChange: handleInput2,
            placeholder: `Enter ${units[1]}`
        }
    ]


    return (
        <>
            <div className="main-wrapper flex flex-col items-center w-full min-h-screen px-4 md:px-8 py-8">


                <h1 className="text-2xl md:text-3xl lg:text-4xl font-bold mb-6">
                    Unit Converter
                </h1>


                <h2 className="text-sm md:text-base text-slate-600 text-center max-w-lg leading-7 mb-8 font-medium tracking-wide">
                    Convert length, weight, and temperature units instantly.
                </h2>






                {/* Tabs */}
                <div className="flex gap-4 mb-4">
                    {Object.keys(unitData).map(tab => (
                        <button
                            key={tab}
                            // onClick={() => setActiveTab(tab)}
                            onClick={() => {
                                setActiveTab(tab)
                                setConversion(unitData[tab][0].key)
                                setValue1('')
                                setValue2('')
                            }}
                            className={`tabs px-4 py-2 rounded cursor-pointer ${activeTab === tab ? 'bg-blue-500 text-white' : 'bg-white text-black'}`}
                        >
                            {tab}
                        </button>
                    ))}
                </div>




                {/* Radio Buttons */}
                <div className="flex flex-wrap gap-4 justify-center mt-2 mb-4">
                    {unitData[activeTab].map(item => (
                        <label key={item.key} className="flex items-center gap-2">
                            <input
                                type="radio"
                                name="conversion"
                                checked={conversion === item.key}
                                // onChange={() => setConversion(item.key)}
                                onChange={() => {
                                    setConversion(item.key)
                                    setValue1('')
                                    setValue2('')
                                }}
                            />
                            {item.label}
                        </label>
                    ))}
                </div>








                {/* Inputs */}
                <div className="flex gap-4 w-full max-w-md">
                    {(reverse ? [...inputs].reverse() : inputs).map((inp, index) => (
                        <input
                            key={index}
                            className="border border-blue-500 mt-2 p-2 w-1/2 outline-none rounded-lg shadow-[0_0_12px_rgba(59,130,246,0.25)]"
                            value={inp.value}
                            onChange={inp.onChange}
                            placeholder={inp.placeholder}
                        />
                    ))}
                </div>




                {/* Reverse Button */}
                <button
                    onClick={() => setReverse(!reverse)}
                    className="swap-btn mt-4 w-10 h-10 bg-black text-white rounded-full flex items-center justify-center text-xl"
                    title='Swap Order'
                >
                    ⇄
                </button>
            </div>
        </>
    )
}


export default UnitConverter