Web Development With Frappe and React

Web Development With Frappe and React

Table of Contents

Full-stack Web App with React & Frappe Framework!

Episode Link

$ bench set-config -g developer_mode 1
$ bench new-app expense-tracker

Getting Doppio

  • For using React with Frappe

https://github.com/NagariaHussain/doppio

$ bench get-app https://github.com/NagariaHussain/doppio

Getting frappe-types

  • For generating Typescript defination file alongside with doctype.js, .py, .json

https://github.com/The-Commit-Company/frappe-types

$ bench get-app https://github.com/The-Commit-Company/frappe-types

Install these apps to your created site.

Creating react app

From Doppio

$ bench add-spa

This will create a react app inside /apps using vite

Now two server need to run:

  1. bench server for frappe
  2. npm server for react

Open up two terminals and fire up the servers. There should be frappe and vite with react running.

This will cause CORS error. So add:

"allow_cors": "*"

to common_site_config.json file.

CSRF Token?

 "ignore_csrf": 1

Add this too.

Type Generation Setting

Type Generation

Installing packages in expenses project

  • react-router-dom
  • react-hook-form
  • react-datepicker
  • chakra-ui
  • “@emotion/react”: “^11.11.4”,
  • “@emotion/styled”: “^11.11.5”,
  • “framer-motion”: “^11.0.28”,

React

Created routes

Components using chakra UI

Expense Record Doctype

Using Frappe react sdk

  const {data, isLoading, error} = useFrappeGetDocList("Expense Record")

Phase 2

Frappe React SDK - The Explainer by The Commit Company

Playlist

Before I followed Build with hussain and tried but couldn’t complete.

Frappe-React-SDK is build with:

  1. Frappe-js-SDK
  2. SWR

Project:

  1. Scope (the project we’re working on): https://github.com/The-Commit-Company/scope
  2. This video’s changes: https://github.com/The-Commit-Company/scope/commit/873255a16280a87538e12f7e87307af1b384a41a
  3. Frappe React SDK: https://github.com/The-Commit-Company/frappe-react-sdk
  4. Doppio: https://github.com/NagariaHussain/doppio
$ bench init react-bench
$ cd react-bench/
$ bench new-app scope_app
$ bench get-app https://github.com/NagariaHussain/doppio
$ bench add-spa
  - React project name: Scope
  - App Name: scope_app
$ bench new-site scope.dev
$ bench use scope.dev
$ bench install-app scope_app
$ bench start

This will create inside /apps/:

  1. scope_app (frappe app)
  2. scope (react app)

Run react app:

$ yarn dev

Still not working!


Phase 3

Try again!

Repeating phase 2 again but this time will log the steps.

Step 1:

Initialize the bench:

$  bench init react-bench

Create a site:

$ bench new-site scope.in

Add to hosts:

$ bench --site scope.in add-to-hosts

alt text

Setting Up.

Step 2:

$ bench new-app scope_app
App Title [Scope App]: Scope
App Description: Project management
App Publisher: atul raj
App Email: atul@raj.com
App License (agpl-3.0, apache-2.0, bsd-2-clause, bsd-3-clause, bsl-1.0, cc0-1.0, epl-2.0, gpl-2.0, gpl-3.0, lgpl-2.1, mit, mpl-2.0, unlicense) [mit]: 
Create GitHub Workflow action for unittests [y/N]: n
Branch Name [develop]:  develop   

Created an app.

Get Dopio:

$ bench get-app https://github.com/NagariaHussain/doppio

Setup react with ts:

$ bench add-spa
Dashboard Name [dashboard]: scope
App Name: scope_app
Which framework do you want to use? (vue, react) [vue]: react
Configure TypeScript? [y/N]: y
Generating spa...
Scaffolding React project...

Step 3:

Install app (scope_app) to site (scope.in)

$  bench --site scope.in install-app scope_app

alt text

Inside bench directory:

/apps/scope_app

alt text

scope –> React app by Doppio scope_app –> App by Frappe

Dependencies under scope

"dependencies": {
    "frappe-react-sdk": "^1.6.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },

Step 4:

Building project

$ bench update --requirements --patch --build

Step 5:

Editing common_site_config.json

 "allow_cors": "*",
 "ignore_csrf": true,

Developer mode:

$ bench set-config -g developer_mode 1

Step 6:

Create .env.local and .env.production

Inside .env.local:

VITE_BASE_PATH=""
VITE_SOCKET_PORT=9009
VITE_SITE_NAME="scope.in"

If your site port number is 8009 your socketio port is 9009 8012 –> 9012

Step 7:

In scope_app

Create a context file for scope.html named scope.py

Add :

import frappe

import json
import re

no_cache = 1

SCRIPT_TAG_PATTERN = re.compile(r"\<script[^<]*\</script\>")
CLOSING_SCRIPT_TAG_PATTERN = re.compile(r"</script\>")

def get_context(context):
    # csrf_token = frappe.sessions.get_csrf_token()
    # frappe.db.commit()
    # context.csrf_token = csrf_token

    if frappe.session.user == "Guest":
        boot = frappe.website.utils.get_boot_data()
    else:
        try:
            boot = frappe.sessions.get()
        except Exception as e:
            raise frappe.SessionBootFailed from e
    boot_json = frappe.as_json(boot, indent=None, separators=(",", ":"))
    boot_json = SCRIPT_TAG_PATTERN.sub("", boot_json)

    boot_json = CLOSING_SCRIPT_TAG_PATTERN.sub("", boot_json)
    boot_json = json.dumps(boot_json)

    context.update({
        "build_version": frappe.utils.get_build_version(),
        "boot": boot_json,
    })

    return context

In scope react app

Inside index.html

<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Scope</title>
</head>

<body>
  <div id="root"></div>
  <script>window.csrf_token = '{{ frappe.session.csrf_token }}';

    if (!window.frappe) window.frappe = {};

    frappe.boot = JSON.parse({{ boot }});

  </script>
  <script type="module" src="/src/main.tsx"></script>
</body>

</html>

Till now in production:

  • SocketIO error
  • csrf token exists

In development:

  • Socketio solved
  • scrf token not working

Step 8:

Update the bench

$ bench update --patch --build --no-backup
  • Socketio error is gone
  • csrf token and boot is there

Step 9:

Add node packages

  • yarn add -D tailwindcss postcss autoprefixer
  • yarn add react-router-dom react-hook-form react-datepicker framer-motion @radix-ui/themes

Step 10:

Login page created.

Printing currentUser but not working!!