Creating a demo app for different operating systems

You want to write cross-platform apps with React? With Electron and a few NPM-packages, this is no problem. In this tutorial I will show you the foundations of developing cross-platform apps that look good on Windows, Mac, and Linux.

The combination of Electron and React makes it easy to write desktop apps for Windows, Mac, and Linux. The combination of Electron and React gives you a familiar development workflow that is much more comfortable than the workflow of native GUI frameworks.

A great example of a cross-platform app that was developed with React and Electron is Alva. Alva is an application to design prototypes for web components.

What is Electron?

Electron allows you to develop desktop apps with web technologies. It is based on the Chromium browser and the Node.js JavaScript runtime.

With the combination of Chromium and Node.js, you can use your web development skills and, at the same time, access the hardware over your host system.

Popular apps that were created with Electron include the text editors Atom and Visual Studio Code, the desktop apps of Skype and Slack, and a lot more. Quite a few startups from the Bay Area seem to use Electron to create apps for their services.

Using Node.js opens a big resource of third-party libraries—you can use almost every library from the Node.js ecosystem.

What is React?

React is a JavaScript library for user interface development. React is developed by Facebook, and developers often use it for the development of single-page apps, which makes it especially suitable for development with Electron. Most Electron apps are single-page apps.

The special thing about React is you can develop your user interface declarative. That means you don't have to change your components by yourself if the state of the app changes. React will change your components automatically according to the current state of the app.

This reactive behavior is the namesake of React itself. Additionally, React gives you some interesting functions for your state management that you can extend with third-party libraries if you need to.

Why Electron and React?

The combination of React and Electron gives you a GUI framework that is very well-documented, very developer-friendly, and can utilize a tremendous ecosystem. This is a combination of features that common GUI frameworks don't give you — especially on Linux.

First Steps

For the following steps I assume you have basic JavaScript knowledge and a few fundamentals about Node.js.

Our first step is to set up Electron with React. The easiest way to do this is using Electron Forge. Electron Forge is a command-line tool that makes it easy to set up Electron projects. It provides several templates for different Electron projects. You can also use it to set up a TypeScript or Angular Project with Electron.

This process needs a minute because the complete runtime of Electron has to be downloaded. At the end you should see in Electron window with a new React app.

npm install -g electron-forge
electron-forge init electron-react-example --template=react
cd electron-react-example
npm install
electron-forge start

Another popular alternative to create React apps with Electron is to use Electron React boilerplate. I have decided to use Electron Forge because it gives you more options for packaging your app. Electron React boilerplate gives you a lot of defaults for React that were more problematic than helpful.

None

Why not create-React-app?

A word about create-React-app: Create-React-app is the official tool from Facebook to produce new React apps. Indeed, it is made for real web applications and not Electron apps.

For example, create-React-app prohibits the use of native Node.js modules. This way it downgrades Electron to a simple browser window, thus destroying the original idea of Electron.

At the end you should have the following directory tree:

We will add changes only to the src directory.

A Demo App

Our demo app will be a replica of the gtk3-demo-application.

None

You find the source code of this tutorial on GitHub: https://github.com/rockiger/electron-react-example.

A first modification

To check if hot reloading is working, we will implement a small modification before we will start with our demo app.

Open the file app.jsxand change the placeholder text.

...
<h2>Demo Application</h2>
...

After you save your changes, the text in your app should also change.

To create a real GUI framework, we need some user interface components. For this we use another library: Blueprint.

Blueprint is a UI Toolkit for React. It gives you a lot of user interface components we can use to build our user interface. To install Blueprint, we add the following code into the command-line:

npm i @blueprintjs/core --save

After that we need to add Blueprint's CSS files into our index.htm. We add the following code before the closing </head>tag:

When you now reload your app, you should see a different font.

To rebuild our demo app we will take the following steps: create the toolbar, integrate a textarea, and finally implement the status bar.

For simplification, we will build everything in one file. In a real application we would split up the components in different files for better code organization.

Toolbar

The toolbar component is called Navbar in Blueprint. A Navbar has a minimum of one NavbarGroup as a child. These NavbarGroup groups can have buttons and dividers as their children.

To recreate the demo application we will add five elements to the Navbar: four buttons and one divider. The button with the downward arrow will be included in a Popover to represent the menu.

The code of our app now looks like this:

First we import the necessary modules, and then we extend the app component. Every React component class needs a render-method. The special thing about the render method is you can mix up HTML and JavaScript in it. (There are also other types of components. Discussing them would would go too far for this tutorial. That's why I am relegating you to the React documentation.)

To recreate the behaviour of the toolbar, we need to add onclick-handlers for the different buttons.

Because Electron differentiates between main- and render-process, we need to import Electron from the main-process into our render-process to access system functions like the alert dialog.

We have done this in the first Lines: we imported the remotemodule and then reassigned the ShowMessageBox method and the appobject in two consonants constant.

The onclick-handlers are simple. They only call the imported Electron method. The folder symbol doesn't get an onclick-handler because in the original demo app it doesn't do it either. Having said that, it could be a good exercise to show a dialogue if the user clicks the folder symbol.

Textarea

Next we will add a simple textarea. We just use a HTML-textarea element for that.

This is not a complete text editor, and it only has a very basic API. There are many libraries on the market to create Powerful editors in Electron and React.

Popular text editors that work well with React are Draft.js and Slate. According to this Github-Issue, Blueprint will add a text-editing solution based on Draft.js, but this ticket is quite old, and it it is unclear when they introduce a solution.

To have the same layout as our demo application, we will change the CSS for the enclosing div-element. We use flexbox to ensure that the textarea uses the whole free vertical area of the application window.

Statusbar

Finally, we create the status bar. The status bar creates two challenges for us: We need to create the layout of the status bar, which is simple, and we need to show the cursor position and the number of characters in our textarea.

We can create the layout easily. We create a div-element with a height of 50 pixels with a light-grey background. We reuse pre-defined colours from Blueprint and add them to the style attribute of the status bar.

The document statistic is a little more complex. We need to add state into our React application. The great thing about React is that its components update if their state changes.

This allows us to draft a simple state model for the application. Anybody who has no experience with React should now refer to the official React documentation and later come back here.

First, we will add and initialize a new state variable statistic. Then we will show the contents of these state variable in our status bar.

Let's introduce the state variable. We add a constructor to our app component. We also bind a method, which we will create later, to the this-object of the component.

Next we add an onKeyDown-attribute to the textarea. This way we can catch user input to our textarea. To show the changes of the textarea in our status bar, we are adding the following text into our status bar element.

React allows us to directly excess the state if we put it into curly braces. When the state changes, the status bar updates automatically.

At last we write an event handler for user input. This event handler will change the state of the application.

We now look at our demo application we see that it looks very similar to the gtk3-demo-application.

None

In the next part to this piece, we will change the design of the app to make it feel more native.

Created with Dictandu