Authored in connection with the Write With Fauna program.
Introduction
This Article will be a walk-through on how to get started with ElectronJS and FaunaDB. We will also be going through some other libraries like ReactJS and AntD. To fully understand this walkthrough I suggest you practice along with and use The Completed project as a Guide.
Prerequisite
This Article is targeted at Beginners to ElectronJS and Fauna, a Reader you are expected to know the following
- React JS
- JavaScript
- NodeJS
- Graphql
- Any design Library like Bootstrap / MaterialUI
What you will Learn
- How to Setup an Electron application from Scratch
- How to Use React and electron
- How to connect Your electron application to a Fauna server using Apollo GraphQL client
- How to perform basic Get, Create and Delete actions on Fauna
ElectronJS
ElectronJS is a Javascript framework that is used that allows the development of desktop GUI applications using web technologies. It utilizes the Chromium rendering engine and the Node.js runtime.
why ElectronJS
- Cross-Platform Support: With ElectronJs you can create GUI desktop applications for multiple operating systems, for example, Windows 10 and macOS
- Write Code once: The same codebase can be used to create both Desktop GUI application and Web applications
- Compiling and Building: Electrons application can work without a specific runtime being installed, this simply means that you can install and run an electron application on a device without NODEJS ( JavaScript runtime Environment) being installed on it
- Flexibility: ElectronJS can be used with most web technology Libraries, for Example ReactJS, VueJS, etc.
In this article, I will be making use of ReactJS to create an Inventory system
Fauna
Fauna is the data API for client-serverless applications. It provides a GraphQL interface and API that supports custom business logic and is integrated with the serverless ecosystem, enabling developers to build and ship faster. It provides a fast, consistent, reliable, and secure infrastructure.
Apollo Client
Apollo Client is a state management tool for JavaScript that enables you to make GraphQL requests and manage data remotely and locally
Use it to fetch, cache, and modify application data, all while automatically updating your UI. In this article, we will use React Apollo Client to interact with Fauna GraphQL API
Check Apollo Docs for more information
AntD
Ant-D short for Ant Design is a Design Library that provides High level reusable react components. They provide components such as
- Icons
- Layout components
- Buttons
- Table component
- Modals
- Toasts, etc
Check Ant Design Documentation for more information
Getting Started
Setup React application using “Create React App”
Run
$ npx create-react-app invetory
Setup Electron with react
Step 1:
To set up electron we are going to start by installing the Packages necessary for it by running
$ yarn add -D concurrently electron-builder electron wait-on electron-is-dev cross-env
- concurrently - Run multiple commands concurrently. Like
npm run watch-js
; in this case, running the react server and electron server simultaneously - wait-on - a package that allows processes run asynchronously; in this case “awaits” the react server before starting the electron server.
- electron- the electron framework that we will be utilizing
Step 2:
Configure the electron by following these steps :
In the electron.js file copy the following code and paste it
const electron = require('electron'); // import electron package
const app = electron.app; // assign the electron 'app' method to the app constant
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
const isDev = require('electron-is-dev');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({ width: 1020, height: 720 });
mainWindow.setMenuBarVisibility(false); // display menu
mainWindow.loadURL(
isDev
? 'http://localhost:3000'
: `file://${path.join(__dirname, '../build/index.html')}`
);
mainWindow.on('closed', () => (mainWindow = null));
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
- Add the Start script to the package.json file
"electron-dev":"concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"",
- Create a /dist/builder-effective-config.yaml file
and populate the file with this configuration
directories:
output: dist
buildResources: assets
files:
- filter:
- build/**/*
- build/**/*
- node_modules/**/*
extraMetadata:
main: build/electron/main.js
appId: com.example.electron-cra
extends: react-cra
electronVersion: 9.0.4
- Direct the electron CLI to the ‘electron.js’ file by adding "main": "public/electron.js",
in the package.json file
Lastly, run
$ npm run electron-dev
If you followed all the steps correctly, you should have your app launched successfully, if you are having troubles, simply clone the React-Electron-Stater repo
Setup Electron with AntD
As stated earlier in this Article, AntD is the design library used in this project, and setting it with our Electron application is as easy as setting AntD up with react. Follow these steps to do so
step 1:
install the following dependencies
$ yarn add antd @ant-design/icons
Step2 :
In the src/index.js file, import AntD stylesheet by add “import 'antd/dist/antd.css';” to the top of the file I will not elaborate much on AntD since it is not the main focus of this Article. For more information visit AntD official doc
Setup Apollo
Apollo Client is a GraphQL client used for GraphQL mutations and queries. In this article, we will use it to interact with the Fauna GraphQL API. To set up Apollo with ElectronJS and ReactJS, you should follow the steps below
step 1:
Install the following dependencies
$ yarn add @apollo/client @apollo/react-hooks graphql
Make sure the access key to your Fauna Graphql API is saved in the .env.local file.
Checkout Migrating a react project from aws appsync to fauna to get started with Creating a Fauna GraphQL API
Note:
Make use of this GraphQL Schema
type Inventory {
product: String! # the name of the product
count: String # count of the product
id: String # special Id given to a product
}
type Query {
allInventories: [Inventory!]
}
In the .env.local file, add an entry for the generated key:
The REACT_APP_FAUNA_SECRET=***
NOTE:
- The config file must be named
.env.local
and not just.env
- React environment variable should start with “REACT_APP_”…
- make sure that you also have a
.gitignore
file in your project’s root directory that contains.env.local
so that your secrets won’t be added to your git repo and shared with others. - You have to restart the react application for changes to take place
Step 2:
Now in the src
directory of your application, add a new file named client.js
with the following content:
import { ApolloClient, InMemoryCache } from "@apollo/client";
export const client = new ApolloClient({
uri: "https://graphql.fauna.com/graphql",
headers: {
authorization: `Bearer ${process.env.REACT_APP_FAUNA_SECRET}`,
},
cache: new InMemoryCache(),
});
The code above simply configures Apollo to make requests to our Fauna database. The uri option specifies the base URI of the GraphQL API, the authorization header indicates that we’re connecting to the specific database instance for the provided key that we generated earlier.
Step 3:
After that, We will replace the code in the index.js
with
import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloProvider } from '@apollo/client';
import './index.css';
import App from './App';
import { client } from './client';
ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
<ApolloProvider \>
<React.StrictMode \>,
document.getElementById('root')
);
Get Inventory Items
Getting data from the Fauna GraphQL API is easy and it is done using the “useQuery” from apollo/react-hook.
To make a query to a GraphQL API follow these steps:
step 1:
import the following dependencies
import { useQuery, gql } from '@apollo/react-hooks';
- useQuery - a react gook that is used to make GraphQL queries
- gql - The gql template literal tag can be used to concisely write a GraphQL query that is parsed into a standard GraphQL AST.
step 2: Write the query
const listInvetoryItems = /**GRAPHQL */ gql`
query {
allInventories {
data {
count
product
id
_id
}
}
}
`;
Step 3:
const { data: inventoryData, error, loading } = useQuery(listInvetoryItems);
Step 4:
Updating the React UI with the data retrieved from Fauna GraphQL query
// From List.js line 64
useEffect(() => {
if (
inventoryData &&
inventoryData.allInventories && // validation
inventoryData.allInventories.data // validation
) {
const newData = inventoryData.allInventories.data.map((data) => ({
...data,
key: data._id, // required by antD Table to manage the state of a rows on a table
}));// mapping response
setData(newData);
}
if (error && loading === false) {
console.log('I think we have an error');
}
}, [inventoryData, error, loading]);
- useEffect is the hook that manages the side-effects in functional components.
- inventoryData is destructured alias of ‘data’ which is the response of the Fauna graphQL call
Add Inventory Item
To add Items to our inventory system we are going to make GraphQL mutations making use of the Apollo client useMutaion hook. To do so, follow the steps below
Step 1 :
import the following hooks at the top of the file
import { gql, useMutation } from '@apollo/react-hooks';
- useMutation is an apollo/react-hooks function that is used to make graphQL Mutations
Step 2:
Write and structure the GraphQl mutation.
const addInventoryMutation = /** GraphQL mutation */ gql`
mutation CreateInventoryItem($data: InventoryInput!) {
createInventory(data: $data) {
count
id
product
_id
}
}
`;
- addInventoryMutation - is a const that contains the GraphQL mutation. You can test and structure a mutation using the graphql playground
Step 3:
Call the useMutation hook, passing the graphQL mutation string and options
const [createItem] = useMutation(addInventoryMutation, {
onCompleted: (data) => {
const { createInventory } = data; // destructure data
setData((state) => {
return [{ ...createInventory, key: createInventory._id }, ...state];
});
},
});
-
useMutation
- is imported from @apollo/react-hooks and is used to execute graphql mutations -
createItem
- useMutation hook returns an array of functions and objects, the first element of the array is a function used to make mutations. The arguments passed to the mutation is the variable of the graphql mutation
Step 4:
// List.js line 88
const onOk = ({ product, count, id }) => {
createItem({ variables: { data: { product, count, id } } });
setIsOpen(false);
};
Explanation:
Please go through the code The Completed project as a Guide To fully understand this Step
- onOk - is a call back function called when the form in the modal is submitted
- createItem is the function (first element of the array) returned by the
useMutation
hook - setIsOpen - is a function used to toggle the form Modal display
Delete Inventory Items
To delete inventory Items follow the steps below
Step 1 :
import the following hooks at the top of the file
import { gql, useMutation } from '@apollo/react-hooks';
- useMutation is an apollo/react-hooks function that is used to make graphQL Mutations
Step 2:
Write and structure the GraphQl mutation.
const deleteInventoryMutation = /** GraphQL delete Mutation */ gql`
mutation DeleteInventoryItem($id: ID!) {
deleteInventory(id: $id) {
count
id
product
_id
}
}
`;
- deleteInventoryMutation- is a const that contains the graphql mutation. You can test and structure a mutation using the graphql playground
Step 3:
Call the useMutation hook, passing the graphQL mutation string and options
const [deleteItem] = useMutation(deleteInventoryMutation, {
onCompleted: (data) => {
setData((state) => {
return state.filter((x) => x.key !== data.deleteInventory._id);
});
},
});
-
useMutation
- is imported from @apollo/react-hooks and is used to execute graphql mutations -
deleteItem
- useMutation hook returns an array of functions and objects, the first element of the array is a function used to make mutations. The arguments passed to the mutation is the variable of the graphql mutation
Step 4:
// List.js line 96
const onDelete = () => {
toDel.forEach((del) => {
deleteItem({ variables: { id: del } });
});
};
Explanation:
Please go through the code The Completed project as a Guide To fully understand this Step
- toDel - is an Array of all selected rows in a table
Conclusion
In this article, we learned how to set up Electron JS, Apollo, ReactJS, and Fauna, We also learned how to make mutations and queries using Apollo. After this walkthrough article, I am confident that you can start creating your desktop applications using ElectronJS, react, and Fauna. Contact me on Twitter for more information.
Top comments (1)
A big thank you to the author for this insightful guide on creating an inventory desktop application with React, Apollo (GraphQL), AntD, ElectronJS, and Fauna. Your step-by-step explanation is incredibly helpful for those diving into the world of desktop application development.
In the spirit of exploring comprehensive solutions, I recently came across an article that delves into the advantages of a custom order management system. It discusses the benefits of tailoring solutions to specific needs, which could be a great read for anyone interested in optimizing their order management workflows.
Thanks again for sharing your expertise, and I look forward to more insightful content!