Cómo construir una calculadora con React Hooks y la API React Context

Si eres como yo, cuando oíste hablar por primera vez de React Hooks quizás estabas un poco ambivalente o confundido por todo el bombo. ¿Cuál es el problema si ya no tengo que escribir componentes de clase? Sin embargo, una vez que me sumergí y pude usarlos, realmente no podía verme regresando a mis días anteriores a Hook. En las palabras inmortales de Blues Traveller, “El gancho te trae de vuelta. No te estoy diciendo ninguna mentira ".

Por un tiempo, estaba buscando una guía sobre cómo usar Hooks en conexión con la API de contexto. Después de encontrar solo unos pocos ejemplos que explicaban el concepto completamente, decidí hacer lo que cualquier buen desarrollador debería hacer: estudiar detenidamente los documentos y construir algo yo mismo. Superarlo y aprenderlo por su cuenta es una de las mejores formas de absorber el conocimiento. Esta es una guía sobre cómo construir el mismo proyecto que hice con el uso de Hooks and Context.

Visión general

Este proyecto será una aplicación de calculadora básica similar a la calculadora de iPhone. Dado que esta es solo una aplicación de escritorio simple, he reemplazado el botón% con un botón Atrás. Aunque no usaría esto para tomar el SAT, definitivamente podrías sumar la cantidad de dedos que tienes.

Hay una versión implementada del proyecto que funciona, o puede ver todo el código en GitHub.

El proyecto

Empezando

Para empezar, solo vamos a utilizar create-react-app. Puede comenzar ejecutando lo siguiente:

npx create-react-app calculatorcd calculatornpm start

Estructura de archivo y CSS

La estructura de archivos de la aplicación debería verse como la siguiente. En la srccarpeta cree los siguientes archivos o simplemente deje App.jsy index.js.

src├── App.js├── index.js└── components ├── BackButton.js ├── Calculator.js ├── ClearButton.js ├── Display.js ├── EqualButton.js ├── FunctionButton.js ├── NegativeButton.js ├── NumberButton.js ├── NumberProvider.js └── styles └── Styles.js

Si desea seguir exactamente las instrucciones, también puede instalar Componentes con estilo para CSS.

npm -i styled-components

A continuación, puede agregar el CSS con estilo desde este enlace al Styles.jsarchivo o agregar el suyo.

Estructura principal de la aplicación

El Calculator.jsarchivo debe configurar la pantalla y el teclado numérico. Debe contener todos los tipos de botones.

Notará que todos los componentes del botón se agregan aquí junto con la visualización del número. Cada uno de los componentes del botón es esencialmente el mismo. Todos deben seguir la misma estructura básica. El zero-buttonconsigue un separada divya que estamos utilizando CSS para el diseño de cuadrícula y tiene que abarcar dos columnas. (PD: si quieres saber más sobre CSS Grid, hice un pequeño artículo sobre los conceptos básicos).

Puede notar que los buttonValueaccesorios solo son necesarios para los componentes NumberButtony FunctionButton. Cada uno de los botones debe seguir la misma estructura básica con un nombre único. Puede hacer referencia a la estructura del archivo arriba para ver qué botones son necesarios. Los botones deben tener el símbolo escrito en el componente del botón si no se pasan a buttonValuetravés de accesorios. Cree uno de estos para cada uno de los tipos de botones en su estructura de archivos.

Después de esto, debería tener la estructura básica de una calculadora. Volveremos a la pantalla en un momento. Ahora vamos a adentrarnos en el funcionamiento interno de la aplicación y ver cómo podemos usar nuestros Hooks y Context.

Construyendo el proveedor de API de contexto

Ahora vamos a crear el NumberProvider.js. Este es el corazón de su aplicación y donde vivirán nuestras funciones. Si nunca ha utilizado la API React Context, es una gran herramienta para ayudar a pasar datos de un componente a otro.

Piense en cuándo tiene componentes que están anidados entre sí. En el pasado, tenías que realizar un “ejercicio de apoyo”. Esto es cuando pasa los datos o la función como accesorios hacia abajo a través de componentes anidados. Esto no es ideal, especialmente cuando comienzas a profundizar varias capas.

Sin embargo, con este componente de proveedor, le permite pasar datos a cualquier componente anidado, sin importar cuán profundo sea. Este proveedor de números envolverá nuestro Appcomponente. Ahora, siempre que queramos obtener datos o utilizar una función que viva en el proveedor, está disponible a nivel mundial. Esto nos evita tener que “perforar” a través de componentes anidados. Mantienes la única fuente de verdad que es la esencia de React. Para comenzar, debe crear el proveedor. Debería tener el siguiente aspecto:

Se crea el proveedor básico y cualquier valor que se pasa ahora está disponible para todos los componentes anidados. Para que esto esté disponible, vamos a empaquetar nuestro Appcomponente para que esté disponible globalmente. Nuestro Apptendrá este código.

Usar el proveedor de contexto

Ahora podemos agregar el código para nuestra pantalla. Podemos mostrar el valor pasando la useContextfunción de la nueva API React Hooks. Ya no tenemos que pasar en accesorios a través de componentes anidados. La pantalla debería verse así:

El número que pasó tres niveles en el NumberProviderestá disponible inmediatamente para el Displaycomponente llamando useContexty pasando nuestro archivo NumberContext. Su pantalla numérica ahora está en funcionamiento, ya que muestra numbercuál hemos establecido en cero.

Ahora, por supuesto, nuestra calculadora muestra un solo cero. Esto es genial si estás contando la cantidad de horas de sueño que duermo con un hijo recién nacido, pero no tanto si intentas agregar algo más, así que usemos algunos ganchos para que esta calculadora calcule.

Introducción a Hooks

Si no ha usado un gancho antes, esencialmente le permite deshacerse de la sintaxis de la clase y, en su lugar, tener un estado dentro de los componentes funcionales. Aquí podemos agregar lo siguiente a nuestro NumberProvider.jsarchivo para crear nuestro primer gancho.

Puede que haya alguna sintaxis que no haya visto. En lugar de escribir nuestra clase con estado, dividimos cada parte del estado en su propia numbervariable más pequeña . También existe la setNumberque actúa de la misma manera que la setStatefunción, pero ahora funciona para una variable específica y se puede llamar cuando sea necesario. useStatenos permite establecer un valor inicial.

Ahora podemos usar todo esto en nuestra función para pasar los valores del botón numérico a la pantalla. En esta aplicación, la calculadora utiliza cadenas para obtener la entrada. Hay comprobaciones para asegurarse de que no pueda tener múltiples .en su número y que no tenga una serie de ceros para comenzar su número.

Componentes de botones de construcción

Ahora puede llamar a esta función utilizando la API de contexto en cualquiera de los componentes anidados.

Ahora tienes una cadena de trabajo de fabricante de números. Puede ver cómo puede comenzar a inyectar los valores que estableció en NumberProviderlos otros componentes de la aplicación a través de la useContextfunción. Estado y las funciones que le afectan se ejercen en el NumberProvider. Solo tiene que llamar en el contexto específico que desee.

You can start to see how this would be great as you start to add more complexity to your app. Say you want a user component to check that you are logged in to use special features. You can create a separate provider that holds the user data and makes that available any nested component.

We can continue to add in functions to our calculator and pass them to the proper component through the useContext function that is built in.

Completed Provider Functions

The completed NumberProvider is found below and contains the following functions that are used with hooks.

  • handleSetDisplayValue sets the value that you are typing into the display. We are checking that it there is only one decimal in the number string and we are limiting the number length to 8 characters. Think of this as more a tip calculator than one to get you through your calculus exam. It takes in the buttonValue property in NumberButton.js .
  • handleSetStoredValue takes our display string and stores it so that we can enter another number. This is our stored value. It will be used as a helper function.
  • handleClearValue resets everything back to 0. This is your clear function. It will get passed to ClearButton.js.
  • handleBackButton allows you to delete your previously entered characters one at a time until you get back to 0. This belongs in the BackButton.js file.
  • handleSetCalcFunction is where you get your math function. It sets if you are adding, subtracting, dividing, or multiplying. It gets passed into the FunctionButton.js file and takes in the buttonValue property.
  • handleToggleNegative does just as the name implies. It allows you do so for either the display value or a stored value after a calculation. This of course goes in NegativeButton.js.
  • doMath does the Math. Finally. Since this is only a simple four function calculator it is just using simple switch function depending upon the functionType that we have in state. We are using parseInt since we are passing our number in as strings. Also we are rounding to only three decimal places, to make sure that we do not have crazy long numbers.

The Finished Display

You will also need a display. In this case it will show the number and the storedNumber along with your functionType. There are a few check such as showing a 0 when you have an empty string as a number.

For brevity sake I am not going to include all of the button functions since they are pretty much the same as the NumberButton.js file above. Just be sure that you pass in a buttonValue prop when necessary, and that you are passing in the correct function from the above list.

See All the Code

If you would like to see the entire code for this project it can be found over in:

GitHub Repo

Calc-U-Later Deploy

Conclusion

I hope that this clears up a bit about how React Hooks and the Context API can be used together. Using these built in React features offers several benefits.

  • Simple to understand syntax and gets rid of the clutter of class components. No more super and constructors. Just a few clean variables.
  • Easier to set and use state within and across components. No more messy prop drilling through multiple component.
  • Eliminates need for Redux in small projects, where you don’t need to hold too much in complex state. You probably aren’t going to re-create Facebook with it, but it will do the job on small-scale apps.

Please let me know your thoughts or if there are any issues that you come across in the code. Hopefully this shone a bit of light onto something that you may not have been familiar with before. React Hooks and Context are great ways to simplify your React apps and write cleaner code.

Check out more of my work and other projects at //theran.co.