Calculadora usando ReactJS con TypeScript

Creando una calculadora bƔsica usando React JS y TypeScript

React JS

React JS es una librería de JavaScript muy popular usada para el diseño de interfaces de usuario, una de las características mÔs importantes de React es que permite separar en componentes los elementos de una pÔgina, esta fragmentación de componentes permite reutilizar código así como trabajar solo en secciones de una pÔgina sin necesidad de recargar todo el documento nuevamente, esta librería es soportada por Facebook y una gran comunidad de desarrolladores lo que la vuelve muy estable y popular.

TypeScript

El uso de TypeScript permite darle mayor estabilidad al incorporar tipos de datos dentro de JavaScript como una especie de lenguaje de programación "tipado", TypeScript es un lenguaje de programación libre y de código abierto desarrollado y mantenido por Microsoft. Es un superconjunto de JavaScript, que esencialmente añade tipos estÔticos y objetos basados en clases.



Código

Components

src/Components/Calculator.tsx


  
  import CalculatorScreen from "./CalculatorScreen";
import CalculatorState from "./CalculatorState";
import Button from "./Button";
import "../Assets/styles.css";

export default function Calculator() {
  return (
   <CalculatorState>
      <div className="calculatorContainer">
        <CalculatorScreen />
        <div className="container">
          <Button type="action" value="AC" />
          <Button type="operator" value="%" />
          <Button type="action" value="←" />
          <Button type="operator" value="/" />
          <Button type="number" value="7" />
          <Button type="number" value="8" />
          <Button type="number" value="9" />
          <Button type="operator" value="*" />
          <Button type="number" value="4" />
          <Button type="number" value="5" />
          <Button type="number" value="6" />
          <Button type="operator" value="-" />
          <Button type="number" value="1" />
          <Button type="number" value="2" />
          <Button type="number" value="3" />
          <Button type="operator" value="+" />
          <Button type="action" value="+/-" />
          <Button type="number" value="0" />
          <Button type="action" value="." />
          <Button type="action" value="=" />
        </div>
      </div>
    </CalculatorState>
  );
}
  
  


src/Components/CalculatorScreen.tsx

import { useAppContext } from "./CalculatorState";

export default function CalculatorScreen() {
  const calculator = useAppContext();
  return (
    <div className="calculatorScreen">
      <div className="calculatorCurrentValue">
        {calculator.currentValue}
        {calculator.isDecimal && "."}
      </div>
    </div>
  );
}


src/Components/Button.tsx

import { useAppContext } from "./CalculatorState";

export default function Button({
  type,
  value,
}: {
  type: string;
  value: string;
}) {
  const calculator = useAppContext();

  const handleClick = () => {
    switch (type) {
      case "number":
        calculator.addNumber(Number(value));
        break;
      case "operator":
        calculator.addOperation(value);
        break;
      case "action":
        calculator.executeAction(value);
        break;
      default:
        break;
    }
  };

  return (
    <button className="calculatorButton" onClick={handleClick}>
      {value}
    </button>
  );
}


src/Components/CalculatorState.tsx



import { createContext, useState, useContext } from "react";

const AppContext = createContext({
  /* state */
  memory: null,
  operation: null,
  currentValue: 0,
  isDecimal: false,
  /* methods */
  addNumber: (value: number | string) => {},
  addOperation: (operation: string) => {},
  getResult: () => {},
  executeAction: (action: string) => {},
});

export default function CalculatorState({ children }: any) {
  const [memory, setMemory] = useState(null);
  const [operation, setOperation] = useState(null);
  const [currentValue, setCurrentValue] = useState(0);
  const [isReset, setIsReset] = useState(true);
  const [isDecimal, setIsDecimal] = useState(false);

  const handleAddNumber = (value: number | string) => {
    if (isReset) {
      if (value.toString() === ".") {
        setIsDecimal(true);
      } else {
        const dot = isDecimal ? "." : "";
        const old: string = currentValue.toString() + dot + value.toString();
        setCurrentValue(parseFloat(old));
        setIsReset(false);
        setIsDecimal(false);
      }
    } else {
      if (value.toString() === ".") {
        setIsDecimal(true);
      } else {
        const dot = isDecimal ? "." : "";
        const old: string = currentValue.toString() + dot + value.toString();
        setIsDecimal(false);
        setCurrentValue(parseFloat(old));
      }
    }
  };

  const handleAddOperation = (op: string) => {
    if (currentValue) {
      if (operation) {
        handleGetResult();
        setOperation(op);
        setIsReset(true);
        setIsDecimal(false);
      } else {
        setOperation(op);
        setMemory(currentValue);
        setCurrentValue(0);
        setIsReset(true);
        setIsDecimal(false);
      }
    }
  };

  const handleGetResult = () => {
    let result = 0;
    if (currentValue && operation && memory) {
      switch (operation) {
        case "+":
          result = parseFloat(currentValue.toString()) + parseFloat(memory);
          break;
        case "-":
          result = parseFloat(memory) - parseFloat(currentValue.toString());
          break;
        case "*":
          result = parseFloat(memory) * parseFloat(currentValue.toString());
          break;
        case "/":
          result = parseFloat(memory) / parseFloat(currentValue.toString());
          break;
        case "%":
          result =
            (parseFloat(memory) / 100) * parseFloat(currentValue.toString());
          break;

        default:
      }

      setCurrentValue(result);
      setOperation(null);
      setMemory(result);
      setIsReset(true);
      setIsDecimal(false);
    }
  };

  const clean = () => {
    setCurrentValue(0);
    setOperation(null);
    setIsReset(true);
    setIsDecimal(false);
  };

  const deleteNumber = () => {
    const index = currentValue.toString().indexOf(".");
    if (index > 0) {
      const numberOfDecimals = currentValue.toString().slice(index + 1).length;
      if (numberOfDecimals == 1) {
        const min = Math.floor(currentValue);
        setCurrentValue(min);
      } else {
        const newNumber = currentValue.toString().substring(0, currentValue.toString().length-1);
        setCurrentValue(parseFloat(newNumber.toString()));
      }
    } else {
      setCurrentValue(Math.floor(currentValue / 10));
    }
  };

  const addDecimal = () => {
    if (currentValue.toString().indexOf(".") > 0) {
    } else {
      handleAddNumber(".");
    }
  };

  const handleExecuteAction = (action: string) => {
    switch (action) {
      case "=":
        handleGetResult();
        break;
      case "AC":
        clean();
        break;
      case "←":
        deleteNumber();
        break;
      case "+/-":
        setCurrentValue(currentValue * -1);
        break;
      case ".":
        addDecimal();
        break;
      default:
    }
  };
  return (
    <AppContext.Provider
      value={{
        memory,
        operation,
        currentValue,
        isDecimal,
        addNumber: handleAddNumber,
        addOperation: handleAddOperation,
        getResult: handleGetResult,
        executeAction: handleExecuteAction,
      }}
    >
      {children}
    </AppContext.Provider>
  );
}

export function useAppContext() {
  return useContext(AppContext);
}

Github Vladimir Salguero

Consulta el repositorio en GitHub





Support YoLeo App on Buy me a coffee!!

buymeacoffee