Hooks and multiple instances of React in Gatsby app - reactjs

I'm trying to use useState in a simple function component in GatsbyJS but I'm getting a seemingly common error in React.
My stripped-down component:
import React, { useState } from 'react';
export default function Header () {
const [isOpen, toggleOpen] = useState(false);
return (
<header>
<button onClick={() => toggleOpen( !isOpen )}>Click Me</button>
</header>
)
}
I get the following error:
Invalid hook call. Hooks can only be called inside of the body of a
function component. This could happen for one of the following
reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app See redacted to quell SO error for tips about how to debug and
fix this problem.
So I read up about the error on this Facebook/React docs page and have determined that my react-dom version is >16.8.0 (I'm using ^16.13.1). My react version is the same.
I'm pretty sure there's nothing wrong with my component function (I basically copied the example from the docs).
The third thing, which I suspect is the issue, is multiple versions of react running simultaneously. When I run npm ls react I get:
+-- gatsby#2.24.73
| `-- gatsby-cli#2.12.107
| `-- react#16.13.1 deduped
`-- react#16.13.1
I tried moving react and react-dom to peerDependencies, as per this response from this Github issues thread, in my `package.json' but that didn't fix the problem, e.g:
"peerDependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"
}
I also tried adding a GATSBY_HOT_LOADER = “fast-refresh” var in a .env.development file according to this Gatsby thread but the issue persisted.
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
Here's my package.json
{
"name": "gatsby-starter-hello-world",
"private": true,
"description": "A simplified bare-bones starter for Gatsby",
"version": "0.1.0",
"license": "0BSD",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"dependencies": {
"gatsby": "^2.24.73",
"gatsby-image": "^2.4.21",
"gatsby-plugin-sass": "^2.3.16",
"gatsby-plugin-sharp": "^2.6.40",
"gatsby-source-filesystem": "^2.3.34",
"gatsby-transformer-sharp": "^2.5.17",
"hamburgers": "^1.1.3",
"node-sass": "^4.14.1",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"eslint-plugin-react-hooks": "^4.1.2",
"prettier": "2.1.2"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-hello-world"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}
And environment info:
System:
OS: Windows 10 10.0.18362
CPU: (8) x64 Intel(R) Core(TM) i5-8300H CPU # 2.30GHz
Binaries:
Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
npm: 6.13.4 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: 44.18362.449.0
npmPackages:
gatsby: ^2.24.73 => 2.24.73
gatsby-image: ^2.4.21 => 2.4.21
gatsby-plugin-sass: ^2.3.16 => 2.3.16
gatsby-source-filesystem: ^2.3.34 => 2.3.34
I've been using Gatsby without issues for some time now so I'm surprised by this error. I suspect it has to do with Gatsby running a version of React, although "deduped", and another version of React also running as seen when I run npm ls react.
Where can I go from here?
Thanks,

I'm also using React#16.13.1. Notably, the gatsby-starter currently only uses React#16.12.1. I ultimately came across an answer from Jeremy Albright on the Gatsby Spectrum that pointed out this could be related to react-hot-loader being deprecated.
Gatsby already has support instead for fast-refresh, you just have to enable the flag.
The fix that worked for me was to add GATSBY_HOT_LOADER=fast-refresh to my .env file.
Source

So I ended up starting over and downloading a fresh copy of the gatsby-starter I was using and that's resolved the issue.
I think I inadvertently installed react and react-dom while I was trying to install a plugin at some point and having multiple versions of react running (one within gatsby) and one installed somewhere else in my project caused the issue.

Related

Parsing error: "parserOptions.project" has been set for #typescript-eslint/parser. The file does not match your project config: .eslintrc.js

I've just used create-react-app to start a new typescript react app and then installed firebase. I ran firebase init, selected the typescript option, enabled es lint and enabled functions.
As soon as I uncommented the boilerplate function code in functions/index.ts, I noticed some warnings in VS Code...
functions/eslintrc.js:
Giving error: "Parsing error: "parserOptions.project" has been set for #typescript-eslint/parser.
The file does not match your project config: .eslintrc.js.
The file must be included in at least one of the projects provided"
functions/tsconfig.json:
functions/src/index.ts:
giving error: "Parsing error: Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.eslint"
functions/package.json:
{
"name": "functions",
"scripts": {
"lint": "eslint --ext .js,.ts .",
"build": "tsc",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "14"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.14.1"
},
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^3.9.1",
"#typescript-eslint/parser": "^3.8.0",
"eslint": "^7.6.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.22.0",
"firebase-functions-test": "^0.2.0",
"typescript": "^3.8.0"
},
"private": true
}
I don't understand these errors. Can someone please help?
Thanks
The first error from TypeScript ESLint is related to not being able to find a project tsconfig.json that matches your functions.
To fix this, we need to tell TypeScript ESLint where the other tsconfig.json is by editing your parserOptions.
.eslintrc.js
// [...]
"parser": "#typescript-eslint/parser",
"parserOptions": {
"project": [
"./tsconfig.json",
"./functions/tsconfig.json",
]
}
// [...]
To fix the parsing issue related to JSX for your React files, you must add the jsx compiler option to your tsconfig.json configurations that include JSX. This will likely be your non-function configuration, and you will most likely need to set it to react-jsx for React v17+ or react in all other cases for Create React App.
tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx"
// [...]
}
// [...]
}
further to the above excellent suggestion by Evelyn Hathaway , and after I installed just the functions with no hosting and I changed the ".eslingrc.js: file
FROM
.eslingrc.js
parserOptions: {
project: ["tsconfig.json",
"tsconfig.dev.json"],
to
.eslingrc.js
parserOptions: {
project: ["./functions/tsconfig.json",
"./functions/tsconfig.dev.json"],
At last the seemed to work after I spent a frustrating day.....

Parcel and rc-table breaks on production build

I have created a sample react app from createapp.dev and added antd in the package.json.
I have been playing around with the table component from antd, and all worked fine when running locally. My snippet looks like this:
import React from 'react';
import {Table} from "antd";
export default class App extends React.Component {
render() {
return(
<div>
<div>Table</div>
<Table dataSource={[]} columns={[]} />
</div>
)
}
}
And the package.json is this:
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"keywords": [],
"author": "",
"license": "ISC",
"scripts": {
"clean": "rm dist/bundle.js",
"start": "parcel src/index.html",
"build": "parcel build src/index.html"
},
"dependencies": {
"antd": "^4.8.2",
"react": "^17.0.0",
"react-dom": "^17.0.0"
},
"devDependencies": {
"parcel-bundler": "^1.12.4",
"#babel/core": "^7.12.3",
"#babel/preset-env": "^7.12.1",
"#babel/preset-react": "^7.12.1"
}
}
Then after running yarn build command it successfully generates the build, but when serving the production build, it breaks with errors like TypeError: s is not a function which comes from Header component of rc-table.
I've searched for a workaround and but wasn't able to find a solution. Does that mean we can't use Table component from antd and why is this issue not detected when running the production build? Has anyone encountered a similar issue?
Edit: Found an online demo with a similar issue
The Parcel Bundler (1.x.x) does not support multiple JS files having the same content.
You can add the following script in scripts/fix-parcel-rc-table-issue.js. Then run it before each build (e.g. "build": "node fix-parcel-rc-table-issue.js && parcel build index.html". ).
const fs = require('fs')
const MARKER = 'CHANGE_CONTENT_HASH'
for (const file of ['BodyContext.js', 'ResizeContext.js', 'TableContext.js']) {
const filePath = require.resolve(`rc-table/es/context/${file}`)
const content = fs.readFileSync(filePath).toString()
if (content.includes(MARKER)) {
continue
}
const newContent =
content + `\nfunction ${MARKER} () { return ${Math.random()} }`
fs.writeFileSync(filePath, newContent)
}
Background
This exact issue has been reported to Ant Design as a bug. They did some digging and found the underlying parcel issue. Here you can find some details.
The Parcel developers don't want to fix this in 1.x.x, but are telling users to switch to the (currently) unstable 2.x.x version. This issue has some more details.
The Parcel developers suggest using the --experimental-scope-hoisting flag. This breaks my build, so I can't verify that this actually fixes the problem. I advise against using this flag in production as it's experimental, so it might have unexpected side-effects (in my opinion Parcels track record generally isn't very good).
Instead I followed FocusCare's advice and simply changed the contents of the files to be unique. This is a nasty hack though, but seems to be the best option until Parcel 2.x.x comes out (or you switch to a more mature bundler).

React native: Unable to resolve "#ant-design/icons-react-native/fonts/antoutline.ttf"

I have a little problem with React Native, I'm using the ant design RN for UI components (https://rn.mobile.ant.design/)
But when i tried to load the ant design fonts , an error appeared. It sayed
"Unable to resolve
"#ant-design/icons-react-native/fonts/antoutline.ttf" from "App.js"
.
the code :
async componentDidMount() {
await Font.loadAsync({
antoutline: require("#ant-design/icons-react-
native/fonts/antoutline.ttf")
})
}
Package.json
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject"
},
"dependencies": {
"#ant-design/icons-react-native": "^1.0.2",
"#ant-design/react-native": "^3.1.3",
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz"
},
"devDependencies": {
"babel-preset-expo": "^5.0.0"
},
"private": true
}
I'm using Expo as a cli
Unfortunately you are trying to use a dependency that requires linking of native code.
From their installation instructions you can see the following:
react-native link #ant-design/icons-react-native
As your app is made with Expo, and the native code is abstracted away from you, it is not possible to use the link command.
Your options are:
Eject your Expo project using expo eject. This will give you full access to the native code. You can read more about it here.
Expo comes with AntDesign icons built in, you can access them using #expo/vector-icons. There is more in the documentation here.
Your easiest option is 2, using #expo/vector-icons. You don't need to install anything to use them.
Just add the following import to your component
import { AntDesign } from '#expo/vector-icons';
Then in your render you can use them in the following way:
<AntDesign name="stepforward" size={32} color="green" />
Making sure to check that the icon you want is available in the directory
If you want to preload your font. The font object is available as a static property on the font component, so in the case above it is AntDesign.font, which should evaluate to something like {antdesign: require('path/to/antdesign.ttf')}
The documentation on fonts and icons on the Expo website is full of great examples.

31.0.0 is not a valid SDK Version. Options are 32.0.0 UNVERSIONED

I am unable to run my app on my simulator as well as device.Earlier it was working.
I have tried every step mentioned in this blog
Official Blog for updation
My package.json is
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"android-windows": "react-native bundle --platform android --dev false --entry-file App.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res && react-native run-android",
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"debugWindow": "start 'rndebugger://set-debugger-loc?host=localhost&port=8081'",
"debugLinux": "open 'rndebugger://set-debugger-loc?host=localhost&port=8081'"
},
"dependencies": {
"expo": "^31.0.4",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-31.0.1.tar.gz",
"react-navigation": "^3.0.8"
},
"devDependencies": {
"babel-preset-expo": "^5.0.0"
},
"private": true
}
And App.json is
{
"expo": {
"name": "AwesomeProject",
"slug": "AwesomeProject",
"privacy": "public",
"sdkVersion": "31.0.0",
"platforms": [
"ios",
"android"
],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
}
}
}
I have tried running npm install 2-3 times but nothing seems to work.
I can't understand why its been suggesting option 32.0.0 when there is no release notes for this option at this link.
Upgrading Expo
This is a known issue https://github.com/expo/expo/issues/3112
It is due to the Expo application from the Play Store having a bug. If you are using v2.10.0 then you should upgrade to v2.10.1
https://github.com/expo/expo/issues/3112#issuecomment-451697372
Sorry guys for the trouble 😞 We've fixed this issue in v2.10.1 that
was released just a few hours later so you should already have an
update.
https://play.google.com/store/apps/details?id=host.exp.exponent&hl=en
WHAT'S NEW
Fix issues when loading experiences with SDK older than 32
You can downgrade it by changing those files that refer to version 32 to the one that your mobile supports like 28:
app.json :
"sdkVersion": "32.0.0" → "sdkVersion": "28.0.0"
package.json :
"expo": "^32.0.0", → "expo": "28.0.0"
"react-native": ".../sdk-32.0.0.tar.gz", → "react-native": ".../sdk-28.0.0.tar.gz"
"jest-expo": "^32.0.0" → "jest-expo": "28.0.0"
try updating your expo application from the play store. It worked for me.
Here is how I fixed mine in case any of the above answers don't work for you.
Open up your app.json and sdkVersion. It was 33.0.0 before upgrading it as below fix the issue.
"sdkVersion": "35.0.0"
This fixed it for me:
Run expo update 35.0.0. (Replace version with your desired version. 35.0.0 is the latest as of this post.) This updates expo, by updating app.json & package.json and installing the latest dependencies.
Referenced from:
https://docs.expo.io/versions/latest/workflow/upgrading-expo-sdk-walkthrough/
Also, check that:
your expo app is the latest version through the app/play store.
your expo cli is the latest version npm install -g expo-cli
If you have run expo update 35.0.0 or other version and it did not solve the error, and if you had ejected your expo project...
Check if you have the right detach properties in your app.json. Note the sdk number on the URL for both iosExpoViewURL and androidExpoViewURL keys.
"detach": {
"iosExpoViewUrl": "https://s3.amazonaws.com/exp-exponent-view-code/ios-v2.13.0-sdk35.0.0-a30ebc9b-3db4-42f4-b677-e468076baf18.tar.gz",
"androidExpoViewUrl": "https://s3.amazonaws.com/exp-exponent-view-code/android-v2.13.0-sdk35.0.0-b816b7af-88da-4ca9-87a5-7438f0c21b6e.tar.gz"
}
try
expo update
Its Working on my case :)
Clear all data and cache of Expo app on your android device. It works for me.
if you are using the Expo app, update them, because the SDK is not are updated
I updated it, and it worked :)
In your package.json
change from
"expo": "^31.0.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-31.0.0.tar.gz",
To
"expo": "^32.0.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
Delete node_module folder and package-lock.json file
Then run
npm i

Size of bundled ReactJS app

I am trying to reduce the size of my reactjs application bundle.js file. For a relatively simple app i have its browserified js file size - 452Kb.
To build it, i use NPM with respective package.json file:
{
"name": "MyApp-React",
"version": "0.0.1",
"description": "My App Description",
"main": "app.js",
"scripts": {
"watch": "watchify app.js -o public/js/bundle.js -v",
"browserify": "browserify app.js | uglifyjs > public/js/bundle.js",
"build": "npm run browserify",
"start": "npm install"
},
"author": "",
"dependencies": {
"axios": "^0.14.0",
"body-parser": "^1.15.2",
"clipboard": "^1.5.12",
"express": "~4.9.7",
"express-handlebars": "~1.1.0",
"express-session": "^1.14.1",
"highlight.js": "^9.7.0",
"node-jsx": "~0.12.4",
"react": "~15.3.1",
"react-dom": "^15.3.1",
"react-maskedinput": "^3.2.4",
"react-modal": "^1.4.0",
"react-router": "^2.8.1"
},
"devDependencies": {
"browserify": "~6.0.3",
"nodemon": "^1.2.1",
"reactify": "~1.1.1",
"uglify-js": "~2.4.15",
"watchify": "^3.1.1"
},
"browserify": {
"debug": false,
"transform": [
"reactify"
]
}
}
Not being an expert in Node JS/ ReactJS development i hope i do somethin wrong, but i cant find what.
For the time being i tried few things: app.js file has a line of code setting NODE_ENV variable to 'production'
process.env.NODE_ENV = 'production';
A second thing i have tried is to use npm prune command with --production parameter. Having this run, i see it removes a lot from node_modules folder, but then npm run build is failing to run as it misses devDependencies. What can i do?
One thing that you could do to lighten the download burden for your users is get react and react-dom from a CDN instead of putting them in your bundle.
Move them from the dependencies section of your package.json to a new section peerDependencies (see npm docs).
Then add tags to your HTML code for loading React and ReactDOM like so:
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.min.js"></script>
→ See React on cdnjs.com
Then you need to change your Browserify config to recognize react and react-dom as external modules.
→ See related question on StackOverflow

Resources