Ionic React Typescript with pug.js, 'Uncaught ReferenceError: React is not defined' when use tsx but not jsx

828 Views Asked by At

Problem: react-app-rewired start works on App.jsx (and .js too) but not on App.tsx (and .ts too)

Steps

  1. I created a boilerplate app with ionic start my-app blank --type=react --capacitor
  2. on package.json, i replace and reinstall accordingly (remove package.lock.json, npm i)
{
    "name": "my-app",
    "version": "0.0.1",
    "private": true,
    "scripts": {
-       "start": "ionic serve",
+       "start": "react-app-rewired start",
-       "build": "ionic build",
+       "build": "react-app-rewired build",
        "test": "react-scripts test"
    },
    "dependencies": {
        "@capacitor/android": "^2.4.3",
        "@capacitor/core": "2.4.3",
        "@ionic/react": "^5.0.7",
        "@ionic/react-router": "^5.0.7",
        "ionicons": "^5.0.0",
        "react": "^16.13.0",
        "react-dom": "^16.13.0",
        "react-router": "^5.1.2",
        "react-router-dom": "^5.1.2",
+       "babel-plugin-transform-react-pug": "^7.0.1",
+       "customize-cra": "^1.0.0",
+       "react-app-rewired": "^2.1.6",
    },
    "devDependencies": {
        "@capacitor/cli": "2.4.3",
        "@ionic/cli": "6.12.2",
        "@testing-library/jest-dom": "^4.2.4",
        "@testing-library/react": "^9.4.0",
        "@testing-library/user-event": "^8.0.3",
        "@types/jest": "^24.0.25",
        "@types/node": "^12.12.24",
        "@types/react": "^16.9.17",
        "@types/react-dom": "^16.9.4",
        "@types/react-router": "^5.1.4",
        "@types/react-router-dom": "^5.1.3",
        "react-scripts": "3.4.0",
        "typescript": "3.8.3"
    },
    "eslintConfig": {
        "extends": "react-app"
    },
    "browserslist": {
        "production": [
            ">0.2%",
            "not dead",
            "not op_mini all"
        ],
        "development": [
            "last 1 chrome version",
            "last 1 firefox version",
            "last 1 safari version"
        ]
    },
    "description": "An Ionic project"
  1. add config-overrides.js file on the project's root folder
const { override, disableEsLint, addBabelPlugin } = require('customize-cra')

module.exports = override(
    disableEsLint(),
    addBabelPlugin('transform-react-pug'),
)
  1. Replace App.tsx with
import React from 'react'
import {
    IonApp,
    IonContent,
    IonHeader,
    IonTitle,
    IonToolbar,
} from '@ionic/react'

declare const pug: any
const App: React.FC = () => {
    return pug`
        IonApp
            IonHeader
                IonToolbar
                    IonTitle My App
            IonContent.ion-padding Add some content here…
    `
}
export default App

  1. On tsconfig.json set "strict": false
  2. npm start (or react-app-rewired start) on project root folder

There's no error on terminal ('Compiled successfully!'), chrome screen is blank, on chrome console:

Uncaught ReferenceError: React is not defined
    at App (main.chunk.js:33)
    ...

Strangely, the app works fine if I change the App extension with .jsx or .js instead of .tsx or .ts

The pug setup also works when setting up a CRA typescript app instead of a ionic start --type=react --capacitor app

Edit: Here is the github for the working/not working repo https://github.com/calvindio/template-ionic-react-ts-pug

1

There are 1 best solutions below

6
On BEST ANSWER

Issue

It looks like the issue is from tsc deleted the unused import which ended up the issue.

For example, this line import React from 'react' won't get included in the compiled code since you didn't return as jsx format.

Likewise, all the import like import { IonApp, ... } from '@ionic/react'; won't be included in the compiled code either. That's why webpack can't map React import correctly.

Solution

From my understanding, I've yet been aware of any option of tsc would still keep the unused imports in the built code. It would be great if you could find that option.

But for now, you could work around by using require keyword which keeps thing sill be imported:

App.tsx

const React = require('react');
const { IonApp, ... } = require('@ionic/react');

// ...