Aprendiendo React: aplicación para calcular propinas.

¿Qué haremos?

Siguiente con el aprendizaje de react y más concretamente de los concepto de estados y hooks, crearemos una pequeña aplicación que permita calcular el coste total de un precio al aplicarle un impuesto seleccionado.

La aplicación es lo de menos, nos enfocaremos en reforzar el trabajo con componentes y asimilar el contexto de trabajo de react.

Comenzando…

Recuerda que el procedimiento que seguíamos para la generación de un proyecto en react era la creación de la estructura de carpetas a través de los comandos de node desde un terminal:

pnx create-react-app tip-calculator
cd tip-calculator

Tras este paso tendremos creado el proyecto y podemos comenzar a trabajar en el.

Desarrollando el código

Por ahora en los proyectos que hemos desarrollado, tal vez por su sencillez, no hemos tenido que tocar el html que se genera por defecto como layout donde la página se mostrará, hablamos del documento index.html ubicado en public:

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

Ahí podemos destacar la existencia del div con id «root», que será referenciado desde la lógica del programa.

Pasemos ahora a la parte principal de este proyecto, el desarrollo del componente que calculará los datos:

Primero definiremos la estructura, sin complicarlo mucho:

import React, { useState } from 'react';

function CalculadoraPropinas() {


  return (
    <div>
      {/* Aquí agregaremos la interfaz de usuario de la calculadora */}
    </div>
  );
}

export default CalculadoraPropinas;

Podemos diferenciar el import de la librería y la inclusión del hook useState para controlar los estados, tras eso, una función que gestiona la lógica del programa y finalmente la llamada a la función con un retorno.

Ahora empecemos a trabajar con los datos, dentro de la función crearemos dos estados para controlar tanto el valor del precio como el del impuesto:

*Recordemos la estructura estándar del hook useState:
const [estado, funciónDeActualización] = useState(valorInicial);

 const [montoFactura, setMontoFactura] = useState(0);
 const [porcentajePropina, setPorcentajePropina] = useState(10);

Esto nos permite definir tanto los estados como las funciones que definirán sus valores.

Y ahora que tenemos toda la estructura lógica creada, podemos crear los dos campos donde el usuario determinará los valores con los que trabajaremos:

  • montoFactura:
<label>Monto de la Factura: $</label>
      <input
        type="number"
        value={montoFactura}
        onChange={(e) => setMontoFactura(parseFloat(e.target.value))}
      />
  • porcentajePropina:
<label>Porcentaje de Propina:</label>
      <select
        value={porcentajePropina}
        onChange={(e) => setPorcentajePropina(parseInt(e.target.value))}
      >
        <option value={10}>10%</option>
        <option value={15}>15%</option>
        <option value={20}>20%</option>
      </select>

En ambos códigos podemos ver una estructura similar: un label que aporta información al usuario y un elemento de formulario que permite la inclusión/selección de datos.

El elemento más característico de estos bloques de código es el evento de cambio de estado, que permite actualizar los estados definidos antes cada vez que se cambian los valores en los campos del formulario, siéntete libre de probar y modificar elementos y valores para ver su efecto una vez la aplicación esté terminada.

Ahora ya podemos rematar los últimos detalles del código, como encerrar estos fragmentos en un div y generar la salida, esta sería la versión funcional del componente:

import React, { useState } from 'react';

function CalculadoraPropinas() {
  const [montoFactura, setMontoFactura] = useState(0);
  const [porcentajePropina, setPorcentajePropina] = useState(10);

  return (
    <div>
      <h2>Calculadora de Propinas</h2>
      <label>Monto de la Factura: $</label>
      <input
        type="number"
        value={montoFactura}
        onChange={(e) => setMontoFactura(parseFloat(e.target.value))}
      />
      <br />
      <label>Porcentaje de Propina:</label>
      <select
        value={porcentajePropina}
        onChange={(e) => setPorcentajePropina(parseInt(e.target.value))}
      >
        <option value={10}>10%</option>
        <option value={15}>15%</option>
        <option value={20}>20%</option>
      </select>
      <br />
      <p>Total a pagar (incluyendo propina): ${(montoFactura * (1 + porcentajePropina / 100)).toFixed(2)}</p>
    </div>
  );
  
}

export default CalculadoraPropinas;

Y solo nos faltaría un detalle, tenemos la lógica y tenemos la vista en la que mostrarla, pero no hemos vinculado ambas cosas, esto se hace en el fichero que gestiona el flujo de lógica de la aplicación, el index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import CalculadoraPropinas from './components/calculator'; // Asegúrate de tener la ruta correcta hacia tu componente


ReactDOM.render(
  <React.StrictMode>
    <CalculadoraPropinas />
  </React.StrictMode>,
  document.getElementById('root')
);

Se importan los elementos necesarios y se realiza un renderizado del componente en el elemento root, recordemos que el renderizado siempre sigue el siguiente formato:

ReactDOM.render(

Qué,

Donde

);

El resultado

El resultado es una página muy sencilla, sin ningún tipo de estilos, que muestra el formulario definido y ante la selección de valor, devuelve el resultado de aplicar la lógica:

¿Te ha resultado útil?

Promedio de puntuación 0 / 5. Recuento de votos: 0