In this tutorial, we’ll be building a React Calculator app. You’ll learn how to make a wireframe, design a layout, create components, update states, and format the output.
To get you inspired, here’s a link to the deployed project we’ll be building.
Also, here’s the source code, just for reference if you need help in any stage of the project.
Since we’ll be building a Calculator app, let’s pick a scope that’s not too complicated for learning but also not too basic for covering different aspects of creating an app.
The features we’ll implement include:
To start off, we’ll draw a basic wireframe to display our ideas. For this, you can use free tools like Figma or Diagrams.net.
Note that, in this phase, it’s not that important to think about colors and styling. What matter most is that you can structure the layout and identify the components involved.
Once we’ve dealt with the layout and the components, all that will be left to do to complete the design is to pick a nice color scheme.
Below are some guidelines for making the app look great:
Based on the criteria above, we’ll use the color scheme shown below.
To start, open the terminal in your projects folder and create a boilerplate template using the create-react-app. To do that, run the command:
That’s the fastest and easiest way to set up a fully working React app with zero config. All you need to do after that is run
cd calculator to switch to the newly created project folder and
npm start to start your app in the browser.
As you can see, it comes with some default boilerplate, so next we’ll do some cleaning up in the project folder tree.
src folder, where the logic of your app will live, and remove everything except
App.js to create your app,
index.css to style your app, and
index.js to render your app in the DOM.
Since we’ve already done some wireframing, we already know the main building blocks of the application. Those are
First create a
components folder inside the
src folder. We’ll then create a separate
.js file and
.css file for each component.
If you don’t want to create those folders and files manually, you can use the following one-liner to get things set up quickly:
Wrapper component will be the frame, holding all the children components in place. It will also allow us to center the whole app afterward.
Screen component will be the top section child of the
Wrapper component, and its purpose will be to display the calculated values.
In the features list, we included display output resize on length, meaning longer values must shrink in size. We’ll use a small (3.4kb gzip) library called react-textfit for that.
To install it, run
npm i react-textfit and then import and use it like shown below.
ButtonBox component, similarly to the
Wrapper component, will be the frame for the children — only this time for the
Button component will provide the interactivity for the app. Each component will have the
In the stylesheet, we’ll also include the styles for the
equal button. We’ll use
Button props to access the class later on.
The base file for rendering in React apps is
index.js. Before we go further, make sure your
index.js looks as follows:
Also, let’s check
index.css and make sure we reset the default values for
margin, pick some great font (like Montserrat in this case) and set the proper rules to center the app in the viewport:
Finally, let’s open the main file
App.js, and import all the components we created previously:
In the example above we have rendered just a single
Let’s create an array representation of the data in the wireframe, so we can map through and render all the buttons in the
Check your terminal and make sure your React app is still running. If not, run
npm start to start it again.
Open your browser. If you followed along, your current result should look like this:
If you want, you can also open the browser’s devtools and test out the log values for each button pressed.
Next, we’ll declare the state variables using React
Specifically, there’ll be three states:
num, the entered value;
sign, the selected sign: and
res, the calculated value.
In order to use the
useState hook, we must first import it in
App function, we’ll use an object to set all states at once:
Our app looks nice, but there’s no functionality. Currently, it can only output button values into the browser console. Let’s fix that!
We’ll start with the
Screen component. Set the following conditional logic to
value prop, so it displays the entered number (if the number is typed in), or the calculated result (if the equals button is pressed).
For that, we’ll use the built-in JS ternary operator, which is basically a shortcut for the
if statement, taking in an expression and returning a value after
? if the expression is true, or after
: if the expression’s false:
Now let’s edit the
Button component so it can detect different button types and execute the assigned function once the specific button is pressed. Use the code below:
Now we’re ready to create all the necessary functions.
numClickHandler function gets triggered only if any of the number buttons (0–9) are pressed. Then it gets the value of the
Button and adds that to the current
It will also make sure that:
commaClickHandler function gets fired only if the decimal point (
.) is pressed. It adds the decimal point to the current
num value, making it a decimal number.
It will also make sure that no multiple decimal points are possible.
Note: I’ve called the handling function “commaClickHandler” because, in many parts of the world, integers and decimals are separated by a comma and not a decimal point.
signClickHandler function gets fired when the user press either +, –, * or /. The particular value is then set as a current
sign value in the
It will also make sure that there’s no effect on repeated calls:
equalsClickHandler function calculates the result when the equals button (=) is pressed. The calculation is based on the current
res value, as well as the
sign selected (see the
The returned value is then set as the new
res for the further calculations.
It will also make sure that:
invertClickHandler function first checks if there’s any entered value (
num) or calculated value (
res) and then inverts them by multiplying with -1:
percentClickHandler function checks if there’s any entered value (
num) or calculated value (
res) and then calculates the percentage using the built-in
Math.pow function, which returns the base to the exponent power:
resetClickHandler function defaults all the initial values of
calc, returning the
calc state as it was when the Calculator app was first rendered:
One last thing to complete the feature list in the intro would be to implement value formatting. For that, we could use a modified Regex string posted by Emissary:
Essentially what it does is take a number, format it into the string format and create the space separators for the thousand mark.
If we reverse the process and want to process the string of numbers, first we need to remove the spaces, so we can later convert it to number. For that, you can use this function:
Here’s the code where you should include both functions:
Check out the next section with full code on how to add
removeSpaces to the handler functions for the
If you’ve followed along, the whole
App.js code should look like this:
Congratulations! You’ve created a fully functional and styled app. Hopefully you’ve learned a thing or two during the process!
Some further ideas for you to explore would be to add some scientific features, or to implement the memory with the list of previous calculations.
If you have any issue reports or feature requests, feel free to leave them in the GitHub repo. If you like the project, feel free to star it.
Madars Biss (also known as Madza) is a passionate software developer and content creator for SitePoint.
A practical guide to leading radical innovation and growth.
© 2000 – 2022 SitePoint Pty. Ltd.