Build a decentralized CRUD application using Typescript, React, and DB3.js
Tags: web3, typescript, react, database
Published: 2023-03-03 10:02:32

## Introduction

[DB3.js](https://github.com/dbpunk-labs/db3.js/) is a JavaScript API development toolkit that complements Web3.js in dApp development. With it, you can write data into the [**DB3 Network**](https://github.com/dbpunk-labs/db3) (a decentralized database), query data, and more.

To help more front-end developers seamlessly switch from the web2 world to the web3 era and quickly build decentralized applications, [DB3.js](https://github.com/dbpunk-labs/db3.js/) adopt the philosophy of the Firebase SDK in mind because [**DB3 Network**](https://github.com/dbpunk-labs/db3) aims to become a decentralized alternative to Firebase Firestore.

Firebase is one of the most popular backend-as-a-service options in modern technology stacks, suitable for multiple platforms, including mobile, Unity, Java, C++, and web. The drawback of the past SDK V8 version was its large size, which caused slow network connections. V9 version made improvements such as functional programming style, no-side-effect imports, etc. These more advanced design concepts reduced the size of the V9 version by 80%. How to design [DB3.js](https://github.com/dbpunk-labs/db3.js/) to be more lightweight and help decentralized applications improve their user experience on mobile devices, etc., is also one of the directions in which [DB3.js](https://github.com/dbpunk-labs/db3.js/) needs to learn from Firebase.

## Using [DB3.js](https://github.com/dbpunk-labs/db3.js/) to Show the CRUD Process of Decentralized Applications

This article will transform a classic demo example of [TodoMVC](https://github.com/tastejs/todomvc) into a decentralized TodoMVC using [DB3.js](https://github.com/dbpunk-labs/db3.js/). We will show how to use [DB3.js](https://github.com/dbpunk-labs/db3.js/) to perform CRUD operations and demonstrate the process of *writing, reading, modifying, and deleting* data in decentralized applications. We will complete a to-do list application as shown below. You can click [here](https://github.com/dbpunk-labs/db3.js/tree/main/examples/todomvc) to view the demo code.

{% embed https://replit.com/@imotai/DB3-Network-CRUD-TodoMVC-Demo %}

During the process, we will display the following CRUD operations:

1. **Create**: Enter a new to-do item, add the to-do item to the list, and complete the addition process by pressing Enter.
    
2. **Read**: Listen to the document in the collection and display the list, including all to-dos, active to-dos, and completed to-dos.
    
3. **Update**: Modify the content of the to-do item; when it is done, click it to mark it as completed.
    
4. **Delete**: Delete the to-do items.
    
![CRUD in the demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9zz6p0idufmuzp8frlvu.png)

(Please note that there may be some instability as we connect to a test node in our network. If you encounter any problems, you can try again later or submit a bug on [GitHub](https://%5Bgithub.com/dbpunk-labs/db3.js/issues/))

## Running the Demo Directly

### Step 1: Start [DB3 Network](https://github.com/dbpunk-labs/db3)

```bash
git clone https://github.com/dbpunk-labs/db3.git
cd db3 && bash install_env.sh && cargo build
# start localnet
cd tools &&  sh start_localnet.sh
```

After starting, you can see network activity similar to the following:


![network log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gj9nwekhvbc44kg5zlyv.png)


### Step 2: Start DB3 CLI, Create Database, and Collection

The database address `0x7720f39c6bf077582ab89797c90ca7701ea82ea9` in the codeblock below is the database address for the todo application to be created next. Then, we create new collection under its database address, named. `todos`.

```bash
(base)  ✘ xuman@192  ~/Documents/GitHub/dbpunkslabs/db3   main  ./target/debug/db3 console       

██████╗ ██████╗ ██████╗ 
██╔══██╗██╔══██╗╚════██╗
██║  ██║██████╔╝ █████╔╝
██║  ██║██╔══██╗ ╚═══██╗
██████╔╝██████╔╝██████╔╝
╚═════╝ ╚═════╝ ╚═════╝ 
@db3.network🚀🚀🚀
db3>-$ new-db
 database address                           | transaction id 
--------------------------------------------+----------------------------------------------
 0x7720f39c6bf077582ab89797c90ca7701ea82ea9 | dw44D6TeBRRZJ8U6fCiVvLPuAvi/B/xBSOAtYMJgUBk=
db3>-$ new-collection --addr 0x7720f39c6bf077582ab89797c90ca7701ea82ea9 --name todos --index '{"id":0, "name":"owner_idx","fields":[{"field_path":"owner","value_mode":{"Order":1}}]}'
send add collection done with tx
o6m7DHogWxaFb6jLQRu5aPzPSwgAP5JK1kBYohNiq7c=
```

### Step 3: Running the Todo Application

Download the todo application code and open the corresponding demo folder.

```bash
git clone <https://github.com/dbpunk-labs/db3.js.git>
cd db3.js/examples/todomvc
```

Next, build:

```bash
yarn
yarn start
```

Then use a browser to open [http://localhost:3000/](http://localhost:3000/) to see the todo application.

## Code Overview

Next, we will explain the project's creation process and provide code examples of key parts.

### File Overview:

```bash
├── src
│   ├── App.tsx
│   ├── base.css
│   ├── context.ts
│   ├── footer.tsx
│   ├── header.tsx
│   ├── index.tsx
│   ├── link.tsx
│   ├── logo.svg
│   ├── main_section.tsx
│   ├── reducer.ts
│   ├── todo_input.tsx
│   ├── todo_item.tsx
│   └── todo_list.tsx
```

Briefly explain the functions of the above files:

* **header**: displays the application's top "what needs to be done", including the form `addTodo` for creating a new to-do item by calling operations.
    
* **footer**: displays aggregation information and controls, as well as a menu classification bar "all/active/completed."
    
* **main\_section**: displays the middle part of the to-do list.
    
* **reducer** and **todo\_item**: define the operations of CRUD and the update of operation status, which is the focus of this article.
    
* **todo\_input**: mainly defines the content input and the event monitoring of Enter.
    

### Component Overview

![relationship of the imports](https://cdn.hashnode.com/res/hashnode/image/upload/v1677775182222/b97f65fc-8432-40fe-896b-220b1eda997d.png?auto=compress,format&format=webp)

The referencing relationship is quite complex, but don't worry; we can see that almost all other components are imported from the reducer, mainly because the reducer file defines almost all states, operations, and state change processes. The CRUD process that we focus on this time is also mainly described by the **Reducer.ts** file.

### State, Operations, and Filtering Processes in Reducer

#### State and Content:

In concept, this Todo application mainly needs to define the following two parts of content:

* A list of to-do items
    
* The current filtering option (all/todo/complete)
    

Each to-do item needs to store the following information:

* The text content of the to-do item (line 17)
    
* A boolean value indicating whether it has been completed (line 18)
    
* The owner of this to-do item data (line 19) (The owner concept is unique to the DB3 Network, and you can view the [issue](https://github.com/dbpunk-labs/db3/issues/271).)
    

The filtering process needs to be determined based on the status information of the to-do items:

* An array of document lists (line 23)
    
* A boolean value indicating whether it is loaded (line 24)
    
* The name of the collection is stored in DB3 (line 26)
    
* The user's wallet address (line 27) (PS. The wallet and its corresponding signature are automatically generated. For quick demo purposes, these pieces of information are currently stored directly in the browser. In the future, [we will support the MetaMask wallet](https://github.com/dbpunk-labs/db3.js/issues/40).)
    
* Where to render and display under which filtering menu (line 28)
    

#### CRUD Operations

In the CRUD process, the first step is to enumerate the CRUD `action` (line 31-36): `INSERT` / `UPDATE` / `QUERY` / `DELETE`; the second step is that since we are not updating synchronously here, that is, the `TodoState` will not be updated immediately when dispatching the `action`. Therefore, we need to define which information changes asynchronously during this process (line 38-47).

Then, we can trigger asynchronous operations according to the CRUD `action` (line 53-99):

`INSERT` will trigger the `collection` and `addDoc` methods of [DB3.js](https://github.com/dbpunk-labs/db3.js/), complete adding the `addDoc` to the corresponding `db` and `collection`, and then trigger the `QUERY` operation accordingly;

`UPDATE` will trigger the `updateDoc` method of [DB3.js](https://github.com/dbpunk-labs/db3.js/), and the data in `DB3Store` will be updated accordingly, and the size and field of the doc will also be updated accordingly. After completion, the `QUERY` operation will also be triggered;

`DELETE` will trigger the `deleteDoc` method of [DB3.js](https://github.com/dbpunk-labs/db3.js/), and the data in `DB3Store` will be updated accordingly. After completion, the `QUERY` operation will also be triggered;

`QUERY` will trigger the `getDocs` method of [DB3.js](https://github.com/dbpunk-labs/db3.js/) to list all docs, and at the same time, it will verify whether the `owner` of each to-do item is the current `userAddress` to filter the to-do items that belong to the current `userAddress`. After filtering, it will be refreshed;

All the above-mentioned [DB3.js](https://github.com/dbpunk-labs/db3.js/) methods (except for `getDocs`) are collectively called [*mutations*](https://github.com/dbpunk-labs/db3/blob/main/docs/images/db3-mutaion.svg) in DB3 Network. They will communicate with DB3 Network; all operation results will be recorded on the chain and cannot be tampered with.

#### Filtering and State Updates

As mentioned earlier, defining the filtering process is another key notion this application must fulfill. The `runfilter` method (lines 103-116) is defined to filter the display based on the status of each to-do item.

The main function of the reducer is to describe the process of generating `nextState` based on `(previousState, action)`. Therefore, after the asynchronous operation is completed, when `REFRESH` is triggered, `nextState` remains unchanged, but the new `todoList: resultSet` is displayed; when `LOADING` and `UNLOADING` are triggered, nextState remains unchanged.

{% embed https://gist.github.com/xuman2019/fb3cf66db5a7d0c7648436f548f448e0 %}

The above is from the [sample code](https://github.com/dbpunk-labs/db3.js/tree/main/examples/todomvc) of `the` TodoMVC. As mentioned earlier, we will add two features in the future:

* Adding support for MetaMask wallet addresses
    
* Add network operation logs in UI
    

If you find our content helpful, please give us a [Github](https://github.com/dbpunk-labs/db3/) ⭐️.

## Reference

[https://dev.to/chroline/why-the-new-firebase-web-v9-modular-sdk-is-a-game-changer-nph](https://dev.to/chroline/why-the-new-firebase-web-v9-modular-sdk-is-a-game-changer-nph)

[https://zhuanlan.zhihu.com/p/551650121](https://zhuanlan.zhihu.com/p/551650121)

[https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers](https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers)