Ein alternativer Titel für diesen Post hätte auch wie folgt lauten können:
"Warum sollte man eine neue Programmiersprache lernen?"

Naja dafür hole ich mal kurz aus:

via GIPHY

Privat schaue ich gerne mal Filme und Serien. Gerne auch mal ein paar Serien parallel. Da kann man schnell den Überblick verlieren. Da hilft mir die Seite Trakt.tv an dieser Stelle ein gutes Stück weiter. Dort kann man Filme und Serien zu einen bestimmten Zeitpunkt einchecken und bekommt so einen guten Überblick über seinen eigenen Fortschritt.

Year in Review 2017

Nun kann man natürlich über die Seite selber einchecken. Ich bin aber ein Freund von nativen Anwendungen und so benutze ich auf meinen Smartphone folgende kleine Applikation:
http://www.cinetrakapp.com/

Genau so eine Anwendung fehlt mir aber für meinen (wiederbelebten) Mac. So, und genau da wollte ich Abhilfe schaffen und eine ReactJS + Electron + Trakt Anwendung. Und naja genau dafür muss ich erstmal ReactJS lernen.
Puh, weit ausgeholt und jetzt starten wir mal in die ersten Schritte.

Meine Struktur und wie baue ich das Ganze?

Also zum Bauen benutze ich Electron Forge. Damit kann man Electron mithilfe eines Templates initialisieren. In diesem Fall habe ich das React Template benutzt und habe damit alles initialisiert:

npm install -g electron-forge
#Initialize a new project
$ electron-forge init traktron --template=react
# Launch your app
$ cd traktron
$ electron-forge start

Danach habt ihr also einen neuen Ordner und da ist dann schon die Grundstruktur angelegt.
Grundstruktur
Zusätzlich habe ich noch Semantic UI für React installiert. Das bringt ein paar UI Grundkomponenten mit.

Der wichtigste Ordner ist natürlich der "src" Ordner. Dort liegt einmal die index.js und die index.html. Die index.js ist wie folgt aufgebaut:

import { app, BrowserWindow } from 'electron';
import installExtension, { REACT_DEVELOPER_TOOLS } from 'electron-devtools-installer';
import { enableLiveReload } from 'electron-compile';

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

const isDevMode = process.execPath.match(/[\\/]electron/);

if (isDevMode) enableLiveReload({strategy: 'react-hmr'});

const createWindow = async () => {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
  });

  // and load the index.html of the app.
  mainWindow.loadURL(`file://${__dirname}/index.html`);

  // Open the DevTools.
  if (isDevMode) {
    await installExtension(REACT_DEVELOPER_TOOLS);
    mainWindow.webContents.openDevTools();
  }

  // Emitted when the window is closed.
  mainWindow.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
};

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow();
  }
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.

Der Code ist für mich noch ein wenig unübersichtlich. Ich kann aber erkennen, das eine index.html geladen wird. Und es werden zusätzlich noch die Developertools von Chrome aufgemacht. Nun aber zu der index.html. Die sieht wie folgt aus:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <link rel="stylesheet" href="../semantic/dist/semantic.min.css">
</head>
<body style="overflow: hidden; background-color: rgba(0,0,0,0); margin: 0" >
  <div id="story-app"></div>
</body>
<script src="./components/main.js"></script>
</html>

Relativ übersichtlicher Code an dieser Stelle. Ich lade da anscheinend ein main.js rein und da kommt das erste Mal so richtig React ins Spiel. Zumindest wirkt es erstmals für mich so.

import React from 'react'; 
import { render } from 'react-dom'
import { Button,
  Container,
  Divider,
  Dropdown,
  Header,
  Message,
  Segment,
  Menu,
  Icon,
  Sidebar } from 'semantic-ui-react'
import App from './components/jsx/App.jsx';

render(
    <App />, document.getElementById('story-app')
)

In ReactJS kann man sogenannte JSX Dateien benutzen. Doch was ist JSX genau? Ich habe das Gefühl, JSX ist eine Art Weiterentwicklung zum herkömmlichen Javascript. Es soll schneller, sicherer und leichter sein. Also zumindest laut Webseite.
Zumindest habe ich damit die "App.jsx" geschrieben:

import React from 'react';
import { Button,
  Container,
  Divider,
  Dropdown,
  Header,
  Message,
  Segment,
  Menu,
  Icon,
  Sidebar } from 'semantic-ui-react'

class App extends React.Component {
    render() {
        return (
            <div>
                <SidebarWithMenuButtonAndContent />
            </div>
        );
   }
}

class SidebarWithMenuButtonAndContent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {menuVisible: false};
    } 
    render() {
        return (
            <div>
                <Menu secondary attached="top">
                    <Menu.Item onClick={() => this.setState({ menuVisible: !this.state.menuVisible })} >
                        <Icon name="sidebar" />Menu
                    </Menu.Item>          
                </Menu>
                <Sidebar.Pushable as={Segment} attached="bottom" >
                    <Sidebar as={Menu} animation="push" width='thin' visible={this.state.menuVisible} icon="labeled" vertical inverted>
                        <Menu.Item><Icon name="home" />Home</Menu.Item>
                        <Menu.Item><Icon name="block layout" />Topics</Menu.Item>
                        <Menu.Item><Icon name="smile" />Friends</Menu.Item>
                        <Menu.Item><Icon name="calendar" />History</Menu.Item>    
                    </Sidebar>
                    <Sidebar.Pusher>
                            <Content />
                    </Sidebar.Pusher>
                </Sidebar.Pushable>
            </div>
      );
   }
}

class Content extends React.Component {
    render() {
        return (
            <div>
                <Segment basic>
                    <Header as="h3">Application Content</Header>
                        <p></p>
                        <p></p>
                        <p></p>
                        <p></p>
                </Segment>
            </div>
      );
   }
}

export default App;

So damit habe ich erstmal ein initiale Basis, auf der ich gut aufbauen kann.
Durch folgenden Befehl kann ich nun alles starten:

electron-forge start

Kapture-2017-10-17-at-19.11.38

Und damit sei auch der erste Beitrag abgeschlossen. Ist ja doch recht lang geworden. Ich denke bei den nächsten halte ich mich ein wenig kürzer. Mal schauen, wie ich mich so mache.