Creating an Inventory desktop Application with React, Apollo (Graphql), AntD, ElectronJS and, Fauna
Tags: fauna, react, graphql, javascript
Published: 2021-03-31 22:25:54


![a display of the inventory application](https://paper-attachments.dropbox.com/s_6E02712F1E789B8E87494429D0311E896DAD12366D6E785640CEE4A571CB72F5_1615422359553_fauna-inventory.gif)


*Authored in connection with the* [*Write With Fauna*](https://fauna.com/blog/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](https://github.com/PhilzAce1/Inventory-system-electon-app-). 

## 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](https://www.apollographql.com/docs/react/) 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](https://ant.design/) 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 :

1. Create a file named ‘electron.js’ in the public folder 
![](https://paper-attachments.dropbox.com/s_6E02712F1E789B8E87494429D0311E896DAD12366D6E785640CEE4A571CB72F5_1615425867996_image.png)


2. In the electron.js file copy the following code and paste it
 ```javascript
    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();
      }
    });
```
3. Add the Start script to the package.json file
```json    
"electron-dev":"concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"",
```
![](https://paper-attachments.dropbox.com/s_6E02712F1E789B8E87494429D0311E896DAD12366D6E785640CEE4A571CB72F5_1615426441257_image.png)


4. Create a /dist/builder-effective-config.yaml file 
![](https://paper-attachments.dropbox.com/s_6E02712F1E789B8E87494429D0311E896DAD12366D6E785640CEE4A571CB72F5_1615428009062_image.png)


and populate the file with this configuration
```yaml
    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
```    
5. Direct the electron CLI to the ‘electron.js’  file by adding 
      "main": "public/electron.js",

in the package.json file

![](https://paper-attachments.dropbox.com/s_6E02712F1E789B8E87494429D0311E896DAD12366D6E785640CEE4A571CB72F5_1615429177803_image.png)


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](https://github.com/PhilzAce1/Electron-React-Starter) 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](https://ant.design/)

## 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](https://dev.to/philzace1/migrating-a-react-project-from-aws-appsync-to-fauna-4mde) to get started with Creating a Fauna GraphQL  API
Note: 
Make use of this GraphQL Schema
```graphql
    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:

```javascript
    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
```javascript

    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**
```javascript
    const listInvetoryItems = /**GRAPHQL */ gql`
        query {
          allInventories {
            data {
              count
              product
              id
              _id
            }
          }
        }
      `;
```
**Step 3:** 
```javascript
     const { data: inventoryData, error, loading } = useQuery(listInvetoryItems);
```
**Step 4:** 
Updating the React UI with the data retrieved from Fauna GraphQL query
```javascript
    // 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.
```javascript
      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 
```javascript
    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:**
```javascript
    // 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](https://github.com/PhilzAce1/Inventory-system-electon-app-) 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.
```javascript
     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 

```javascript
    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:**
```javascript
    // 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](https://github.com/PhilzAce1/Inventory-system-electon-app-) 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](https://twitter.com/philzace1) for more information.