Richie Pineda

Aug 17, 2019

6 min read

Using Electron’s ipcRenderer and ipcMain to Create a Desktop Application

Taking a page from Event Oriented Programming.

Photo by Helloquence on Unsplash

So you want to build an offline desktop app, huh? There’s Event Emitters for that.

QLStico, essentially being a GraphQL infused tribute to Postico, was designed to be a lightweight PostgreSQL database visualizer and CRUD operator. Despite its simplicity, the trouble came when we as web developers had to implement a more traditional Model-View-Presenter approach to development. We found that our app would be dealing almost exclusively with the the internal PostgreSQL files of a computer and therefore a traditional server-client setup with routes and URLs did not fit the purpose. Maybe you’re on the same boat, deciding whether you want to build some sort of standalone, offline application or tool. If that is the case like it was ours, the question of “how do you service all the navigation and retrieval of information without a server?” comes about to which Electron answered: ipcRenderer and ipcMain. To quote straight from Electron’s docs:

app
┣ pg
┃ ┗ pg.js
┣ main
┃ ┣ main.js
┣ components
┃ ┣ AllDBs.js
//Inside AllDBs,js file:import React, {useContext} from 'react';
const { ipcMain } = require('electron');
const AllDbs = props => { (...) function getTablesFromDb(dbName) {
ipcRenderer.send("GET_TABLE_NAMES", dbName);
ipcRenderer.once("GET_TABLE_NAMES_REPLY",
(_, tableNamesResponse)=> {
setTableNamesInContext(tableNamesResponse);
props.history.push('/allTables');
};
);
};
return (...)
};
// Inside pg.js file:const pg = require('pg')(...)const getAllTables = dbName => {    DB_CONNECTION.setDatabase(dbName);
const pool = new pg.Pool(DB_CONNECTION);

try {
const response = await pool.query(
`SELECT table_name FROM information_schema.tables
WHERE table_type = 'BASE TABLE' AND table_schema NOT IN
('pg_catalog', 'information_schema',
'management','postgraphile_watch') and
table_name!='_Migration'`
);
return response.rows.map(({ table_name: tableName })
=> tableName);
} catch (error) {
return error.message;
}
};module.exports = { getAllTables }
// Inside main.js file:const { ipcMain } = require('electron');
const getAllTables = require('../pg/pg.js')
(...)ipcMain.on("GET_TABLE_NAMES", (event, dbName) => {
const tableNames = getAllTables(dbName);
event.reply("GET_TABLE_NAMES_REPLY", tableNames);
});