13
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TECH::CAMPAdvent Calendar 2016

Day 14

[ Electron + React + Redux ] クラウド管理式マークダウンエディターを作ってみた

Last updated at Posted at 2016-12-14

クラウドで管理出来るマークダウンエディターって中々いいものがないですよね。
Webで作ってもいいんですが、Electronというものを使えばJavaScriptでデスクトップアプリが作れるようなので使ってみようと思います。

※ React+ReduxとElectronメニューの連携についてだけ知りたいという方は、最初の方は読み飛ばしてください

Electronとは

  • テキストエディターである「Atom」を開発するために生まれたデスクトップアプリケーションエンジン
  • HTML+CSS+JavaScriptでクロスプラットフォームなデスクトップアプリケーションを開発出来る
  • 著名なアプリケーションでも採用されている
    • Atom
    • Slack
    • VisualStudio Code

作ったアプリ

機能

マークダウン編集・保存・削除

Electronの基本

まずはElectronをインストールしましょう。

yarn global add electron-prebuild

Electronはpackage.jsonのmainで指定しているJSファイルをエントリポイントとして使用します。
ここでは、index.jsとします。

package.json
...
"main": "index.js",
...

index.jsにはこのように記述します。

index.js
const { app, BrowserWindow } = require('electron');

let mainWindow;

function createWindow (){
  mainWindow = new BrowserWindow({width: 800, height: 600});
  mainWindow.loadURL(`file://${__dirname}/frontend/index.html`);
  mainWindow.on('closed', function(){
    mainWindow = null;
  });
}

app.on('ready', function(){
  createWindow();
});

app.on('window-all-closed', function(){
  if(process.platform !== 'darwin'){
    app.quit();
  }
});

app.on('activate', function(){
  if(mainWindow === null){
    createWindow();
  }
});

7行目にmainWindow.loadURL(.../index.html)という記述がありますね。
ElectronはこのloadURLに指定されているHTMLファイルをデスクトップアプリケーションとして表示してくれます。
なのでindex.html

index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Markdown Editor</title>
  <link rel="stylesheet" href="./index.css">
</head>
<body>
  <div id="root"></div>
  <script src="./bundle.js"></script>
</body>
</html>

と記述し、(Reactなどを使用している場合はコンパイル後の)JSファイルを読み込ませれば簡単にデスクトップアプリケーションを作成することが出来ます。

しかし、このままではただHTMLを表示するだけなのでWebアプリケーションと大差ないですよね。
Electronはデスクトップアプリケーション特有のメニューステータスバーにアクセスするAPIを提供してくれています。

今回作ったアプリケーションでもメニューを使用しているので、React+Reduxとメニューを組み合わせる方法を紹介しようと思います。

React+Redux+Electron

React+Reduxを使ってElectronを実装している場合、メニューからActionを発行したくなることがあると思います。(自分はありました。)

メニューを実装するだけであればindex.js

index.js
...
function createMenu (){
  const template = [
    {
      label: 'Electron',
      submenu: [
        {
          label: 'Quit',
          accelerator: 'CommandOrControl+Q',
          click: function() { app.quit(); }
        }
      ],
    },
  ];

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
}

app.on('ready', function(){
  createWindow();
  createMenu();
});

以下のような記述を追記するだけで簡単に実装出来ます。
labelとsubmenuの対応は以下の通りです。

png

Actionを発行するメニューを実装する場合は

index.js
...
submenu: [
  {
    label: 'Action',
    accelerator: 'CommandOrControl+Shift+A',
    click: function(){
        mainWindow.webContents.send('dispatch', { type: 'action_type' });
    }
  }
]

React側は

./lib/ipcRenderer.js
const ipcRenderer = window.require('electron').ipcRenderer;

export default ipcRenderer;
./index.js
import ipcRenderer from './lib/ipcRenderer' 
...
const store = configureStore();

ipcRenderer.on('dispatch', (e, action) => {
  store.dispatch(action);
});

render(
  ...
);

と記述することで実装することができます。
Electronはメインプロセスとレンダラプロセスとプロセスが分かれているため、プロセス間通信を行う場合はipcというものを使う必要があります。

しかし、引数が動的に設定したい場合はこの実装だと実現不可能ですね。
今回作成したアプリケーションでも、Command+Sでエディターの値をデータベースに保存する機能を実装しているんですが、上記の方法だと引数にエディターの値を設定できなかったので実現不可能でした。

その解決方法も紹介します。
結論から言うと、設定したキーバインドが押下されると、値を保存する関数が発火する方法を取りました。

コードは以下の様になっています。

index.js
...
label: 'Edit',
submenu: [
  {
    label: 'Save',
    accelerator: 'CommandOrControl+S',
    click() {
      mainWindow.webContents.send('save');
    }
  },
]
...
/component/Editor.jsx
import ipcRenderer from '../lib/ipcRenderer';
...
export default class Editor extends Component {
  constructor (props){
    ...
    ipcRenderer.on('save', () => {
      this.onSave();
    });
    ...
  }

  onSave(){
    const { content } = this.props;
    this.props.onSave(content);
  }
}

こうすることでコマンド+Sが押下された際にComponentのonSave関数が動く実装が可能です。

まとめ

Electronは今回始めて触ってみましたが、非常に使いやすい印象を受けました。React+Reduxと組み合わせて使用していて、尚且つメニューを使用している参考がなかったので少し難しかったですが、同じようなことをしている方がいれば参考になると嬉しいです。

ReactNativeを使えばReactでスマホアプリも作れるので、Reactが書ければデスクトップ・スマホ・Web全て作ることが可能ですね。素晴らしい限りです。

13
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?