You can’t truly learn it unless you build something useful with it.

That is the rule I always try to adhere to whenever I want to learn anything new. And by useful I mean a finished product or at least a proof of concept, which can be used by everyday people.

When I finally got my hands on Electron, I had an idea in my head of a desktop app where you browse shows, add your favorite ones, and have a convenient dashboard with episodes coming out soon. There’s an API for that called thetvdb which I could easily employ. So I gave it a go. The end result can be played with right now on GitHub.

In this article, I’m going to walk you through the process of using Electron with React from the very beginning. We’ll start with the basics and cover the required setup for making friends with React and ES2015 (spoiler: it’s soooo much easier than you probably think). Next, we’ll use the React router and create some views (which are just good old web pages). Finally, we’ll learn how to download data and store it in a filesystem (yes, like grown-ups!).

But first, let me tell you why Electron is huge.

Electron overview

Electron is a platform widely used by tech companies, including monsters like ShopifySlackWordPress and of course Github’s Atom, for which it was initially developed.

In a nutshell, Electron is a combination of a browser engine and a Node.js environment. The practical meaning of this is that the environment you write code in has both access to the DOM and the ability to work with the Node.js API. It allows the modest web developer like you and me build complex cross-platform desktop applications.

For example, you can do things like this:

You can both work with the app as you do with a web page and at the same time use the features of the OS like this is a native app. So you have all that flexibility of the web combined with the power of a native app, which creates fantastic opportunities.

How to read this tutorial

This is a step-by-step tutorial. I tried to make sure that after every step we have a runnable application with a working functionality. Every step has a link you can click on to see the whole commit.

The complete code is available on GitHub, so sometimes, when I omit some chunks to save the space, don’t hesitate to lookup the full version.

Enough words, let’s get to action.

Step 1. Let’s run an Electron app

Check the whole commit.

First, let’s start a new project with yarn:

Now let’s install the Electron package:

…and add the command to package.json

If you’re not familiar with the script directive, it allows us to create shortcuts to run the npm (or yarn) commands.

If you try to launch it now with yarn start, you’ll get an error. That’s because we don’t have index.js yet. Let’s create it.

OK, now this may look like too much. But actually this is just a boilerplate required to create a window. onActivated is here to simulate macOS behavior: when you click on the app in the dock, it opens a new window but doesn’t really quit when you close it. loadPage actually takes the index.html file and loads it into the browser. So let’s create it as well.

Run it with yarn start and you should see our new shiny app.

Step 2. Introducing React into the mix

Check the whole commit.

I don’t think I need to tell you what React is when it’s become a de facto industry standard. What I’m going to tell you is how to setup it to work with Electron. Typically at this point, you will want to introduce webpack and spend tons of time configuring it right. But there’s a better way. Meet the electron-compile package.

That’s kinda it. Now you can use ES2016, SASS, React’s JSX, you can use PUG templates for your pages, whatever you like. If it sounds incredible, that’s because it is. But the people behind that package managed to make everything to work seamlessly. All you need to do is add a file to the web page and provide a proper type attribute. Now let’s add a React entry point to our app:

The src/js/bootstrap.js is going to be our app’s entry point.

Note: when we import a file, the root dir in every case is src. All paths are taken relative to it because this is the directory in which our index.html file resides.

src/js/components/app.jsx is the place where we’ll define our routes in the next step:

Update the application and you should see the “Hello, React” text.

Step 3. Creating routes and building the layout

Check the whole commit

Our app is going to have just two routes. The first one is the dashboard, and the second is search page to look up new shows. We will use the react-router for that.

Note, that we also added moment.js. That’s because I’m very bad at dealing with JS dates.

Wow. There are lots of things going on here. But before that, let’s add the Photon styles framework to make our app look more appealing (you may have already noticed that we use classes from that library in our layout).

Let’s now create placeholders for home and search components. We will work on them in the next part.

Now when you run the project, you should be able to navigate between the views using the side menu.

Step 4. Search for a show

Check the whole commit

OK, now we’re ready for some real work. What we’re going to do is create a simple form to look for a particular show in thetvdb database, using their public API. Then we can add the show to our local store (which means downloading and unzipping the XML file with the show’s information).

In order for the API to work, we’ll need an API key. You can get it here. Then you should export THETVDB_API_KEY variable, because our app is going to use it.

I’m not going to paste the whole file here (see the commit), but let’s take a quick glimpse at how the API works:

Nothing too fancy is going on here, apart from the fact that we’re using the node API (the request module), not the browser’s. This is so we don’t have to deal with CORS issues or other related stuff. It’s just like server-side code.

Let’s add some more npm dependencies:

We also added some more styles, but I’m not going to include them here in the interest of not wasting space. You can look it up in the commit.

We added a simple input field. When the text in it changes we use the API module to search in thetvdb API, and then we put the results into the results instance variable. Notice the invocation of setState. That’s the way to tell React that the state has been updated, so the view should be re-rendered. For every show we render a Show component. Let’s add it as well:

Notice the line show.followed = store.isFollowed(this.state.show.id). We know that the show is followed if we have the corresponding XML file in our store directory (more on that later). That’s what the store module is for. The second time we use it is when we “follow” the show, which means we are downloading the show file from thetvdb database to our local directory.

The store module is responsible for storing and retrieving data from the filesystem. Since thetvdb API gives us the show’s data as zipped files, we will store those files in a special dot-directory ~/.eltv. You can find the complete code for store on GitHub, but here’s a quick glimpse of the store.add method.

Here we are checking if the local storage directory exists and if not, creating it before downloading the file. The magic of Electron is that we can use the fs module here to work with the filesystem.

Run the project now, and you should be able to look for a show and add it to your list of shows.

Step 5. Displaying added shows in the sidebar

Check the whole commit

Let’s now display the shows we’ve already added in the sidebar. To do that we have to change the app.jsx component. When the component is mounted, we will read all shows that we have downloaded.

Step 6. Home view

Check the whole commit

Finally, we’re going to create a home view with several blocks showing new episodes released from the last week, coming up later this month, and the next month. For that we’re going to read the data from the show’s files we downloaded earlier, parse it to JSON and make some basic date comparisons. I’m not going to post the whole file this time since it’s huge, but feel free to refer to the commit.

Notice that we do store.updateAll every time on componentDidMount. That’s because we need to make sure that our downloaded files are up-to-date. This logic, of course, could be smarter, but I don’t want to complicate it any further.

While the downloading is in progress we put a placeholder saying “Fetching Data From thetvdb.com.” Then we read the files from the filesystem, parsing them and grouping them according to the release date.

And that’s mostly it!

Conclusion

Hopefully, by this time you understand the real power of Electron.

By combining the web-dev mentality and the mighty node.js engine, Electron allows for quick development of rich desktop applications and gives that opportunity to a wider audience of web developers. People can build apps even if they don’t necessarily know or care about the platform’s underlying details, and they don’t have to know Objective-C or C#.

We are now able to create desktop apps with only our knowledge of web technologies. That’s just pure magic to me.

5 links for diving deeper

The following two tabs change content below.
mm

Janis Triandaphilov

Janis is a Ruby and JavaScript enthusiast. He runs the Full-Scale JavaScript newsletter.
mm

Latest posts by Janis Triandaphilov (see all)

Comments

comments