eslint/eslint-plugin-react:not finding .jsx files - reactjs

I'm using eslint on a react app for the first time, and while it's checking .js files perfectly well, it's not finding any .jsx files. Admittedly my understanding is hazy, but I thought eslint-plugin-react automatically scanned .jsx files as well with parserOptions.ecmaFeatures.jsx set to true?
If I run npm run:lint -- --ext .jsx then jsx files are scanned correctly, but not with a default npm run:lint command
My .eslintrc here:
{
"plugins": [
"react"
],
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"env": {
"es6": true,
"browser": true,
"node": true,
"mocha": true,
"jest": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"rules": {
}
}

It looks like using the --ext CLI flag is the only way to specify file extensions. See the documentation below.
https://eslint.org/docs/2.0.0/user-guide/configuring#specifying-file-extensions-to-lint
One thing you could do is to include the flag as part of your npm command. For example, npm run lint could run eslint --ext .jsx so that you don't have to type it manually.

Related

how to configure styled jsx in Eslint

I'm setting up an environment this way to work with a ReactJs/Next.js project that uses 'styled jsx', but eslint can't fix the css flaws in the middle of the code.
How can I best configure eslint to work with the project I'm working on?
{
"parser": "#babel/eslint-parser",
"extends": [
"airbnb",
"plugin:react/recommended"
],
"env": {
"es6": true,
"browser": true,
"node": true,
"jest": true
},
"settings": {
"import/core-modules": ["styled-jsx", "styled-jsx/css"],
},
"plugins": [
"react",
"react-hooks"
],
"parserOptions": {
"sourceType": "module",
"allowImportExportEverywhere": true
},
"rules": {
// ..rules
}
}
Check this out:
https://github.com/vercel/styled-jsx#eslint
If you're using eslint-plugin-import, the css import will generate errors, being that it's a "magic" import (not listed in package.json). To avoid these, simply add the following line to your eslint configuration:
"settings": {"import/core-modules": ["styled-jsx/css"] }
This should remove any errors - but you won't get highlighting.

Jest Cannot use import statement outside a module [duplicate]

If I use import/export from ES6 then all my Jest tests fail with error:
Unexpected reserved word
I convert my object under test to use old school IIFE syntax and suddenly my tests pass. Or, take an even simpler test case:
var Validation = require('../src/components/validation/validation'); // PASS
//import * as Validation from '../src/components/validation/validation' // FAIL
Same error. Obviously there's a problem with import/export here. It's not practical for me to rewrite my code using ES5 syntax just to make my test framework happy.
I have babel-jest. I tried various suggestions from GitHub issues. It is no go so far.
File package.json
"scripts": {
"start": "webpack-dev-server",
"test": "jest"
},
"jest": {
"testPathDirs": [
"__tests__"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"testFileExtensions": ["es6", "js"],
"moduleFileExtensions": ["js", "json", "es6"]
},
File babelrc
{
"presets": ["es2015", "react"],
"plugins": ["transform-decorators-legacy"]
}
Is there a fix for this?
From my answer to another question, this can be simpler:
The only requirement is to configure your test environment to Babel, and add the ECMAScript 6 transform plugin:
Step 1:
Add your test environment to .babelrc in the root of your project:
{
"env": {
"test": {
"plugins": ["#babel/plugin-transform-modules-commonjs"]
}
}
}
Step 2:
Install the ECMAScript 6 transform plugin:
npm install --save-dev #babel/plugin-transform-modules-commonjs
And that's it. Jest will enable compilation from ECMAScript modules to CommonJS automatically, without having to inform additional options to your jest property inside package.json.
UPDATE 2020 - native support of ECMAScript modules (ESM)
According to this issue, there is native support of ESM from jest#25.4.0. So you won't have to use babel anymore. At the time of writing this answer (05/2020), to activate that you need to do three simple things:
Make sure you don't transform away import statements by setting transform: {} in config file
Run node#^12.16.0 || >=13.2.0 with --experimental-vm-modules flag
Run your test with jest-environment-node or jest-environment-jsdom-sixteen.
So your Jest configuration file should contain at least this:
export default {
testEnvironment: 'jest-environment-node',
transform: {}
...
};
And to set --experimental-vm-modules flag, you will have to run Jest as follows:
node --experimental-vm-modules node_modules/jest/bin/jest.js
Also note in the Github issue that this approach does not yet support the jest object. So you may need to import it manually:
import {jest} from '#jest/globals'
(I hope this will change in the future)
For an updated configuration, I'm using https://babeljs.io/setup#installation
Select JEST and be happy:
As a reference, the current configuration:
npm install --save-dev babel-jest
In your package.json file, make the following changes:
{
"scripts": {
"test": "jest"
},
"jest": {
"transform": {
"^.+\\.jsx?$": "babel-jest"
}
}
}
Install babel preset:
npm install #babel/preset-env --save-dev
Create a .babelrc file:
{
"presets": ["#babel/preset-env"]
}
Run your tests:
npm run test
In package.json, kindly set like this one: "test": "node --experimental-vm-modules node_modules/.bin/jest"
Should be good!
It's a matter of adding stage-0 to your .babelrc file. Here is an example:
{
"presets": ["es2015", "react", "stage-0"],
"plugins": ["transform-decorators-legacy"]
}
I encountered the same issue.
These are what I did:
yarn add --dev babel-jest #babel/core #babel/preset-env
Make file jest.config.js in rootDir.
module.exports = {
moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "json"],
transform: {
'^.+\\.(js|jsx)?$': 'babel-jest'
},
testEnvironment: 'node',
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/$1'
},
testMatch: [
'<rootDir>/**/*.test.(js|jsx|ts|tsx)', '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
],
transformIgnorePatterns: ['<rootDir>/node_modules/']
};
Then make file babal.config.js in rootDir.
Go like this:
module.exports = {
"presets": ["#babel/preset-env"]
}
Below is how I setup jest, typescript and ES Modules for my project.
jest.config.js
/**
* #type {import('ts-jest/dist/types').InitialOptionsTsJest}
* To configure ESM support, see: https://kulshekhar.github.io/ts-jest/docs/guides/esm-support
*
**/
export default {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
extensionsToTreatAsEsm: ['.ts'],
globals: {
'ts-jest': {
useESM: true
}
},
setupFiles: ['<rootDir>/__tests__/setup.ts'],
};
tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"outDir": "./dist",
"moduleResolution": "node",
// "strict": true,
"esModuleInterop": true,
"inlineSourceMap": true,
}
}
package.json scripts and devDependencies
"scripts": {
"start": "node ./dist/server.js",
"dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
},
"devDependencies": {
"#jest/globals": "^27.4.4",
"#types/express": "^4.17.13",
"#types/jest": "^27.4.0",
"#types/supertest": "^2.0.11",
"cross-env": "^7.0.3",
"supertest": "^6.2.1",
"ts-jest": "^27.1.3"
}
__tests__/setup.ts
import dotenv from 'dotenv';
dotenv.config({
path: './.env.test'
});
all is explained in the jest docs: jest docs
1.
npm install --save-dev babel-jest #babel/core #babel/preset-env
in file: babel.config.js
module.exports = {
presets: [['#babel/preset-env', {targets: {node: 'current'}}]],
};
In addition to installing babel-jest (which comes with Jest by default now) be sure to install regenerator-runtime.
To add support for React and react-testing-library it may be useful to eject CreateReactApp and take all needed Jest configuration from the package.json. It is ready to use with another bundler, Rollup in my case.

next.js Setting up ESLint for NextJs

I have created basic next.js app using "npx create-next-app" and .eslintrc.json file created to add eslint rules.but it's not working.how to add linting rules to nextjs config
{
"env": {
"browser": true,
"es6": true
},
"extends": [
"standard"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly",
"React": "writable"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"react/react-in-jsx-scope": "off"
}
}
I have tried this solution - https://medium.com/#joelmasters/setting-up-eslint-for-nextjs-37163d4cabaa
Update
NextJS now has official guide to add eslint to project: https://nextjs.org/docs/basic-features/eslint
Additionally you need to install ESLint extension.
Also, If you're looking for ESLint with typescript support: https://gourav.io/blog/nextjs-cheatsheet
Old answer:
Install ESLint
npm i eslint --save-dev
Install ESLint plugins:
npx install-peerdeps --dev eslint-config-airbnb
Above single command will install 6 plugins: eslint-config-airbnb, eslint-plugin-import, eslint-plugin-react, eslint-plugin-react-hooks, and eslint-plugin-jsx-a11y. You can also install these plugins individually.
Install babel eslint
npm i -D babel-eslint
Install prettier plugin (optional, so that prettier doesn't mess up with linting)
npm i -D eslint-config-prettier eslint-plugin-prettier
Your "devDependencies" should look something like this:
"devDependencies": {
"babel-eslint": "^10.1.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.1.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.20.0",
"eslint-plugin-react-hooks": "^2.5.1"
}
Now, create a file .eslintrc.json at root of project.
Paste below config:
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"parser": "babel-eslint",
"extends": [
"eslint:recommended",
"airbnb",
"airbnb/hooks",
"plugin:react/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:jsx-a11y/recommended",
// "plugin:react-hooks/recommended",
// always put prettier at last
"prettier"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true // enable linting for jsx files
},
"ecmaVersion": 11,
"sourceType": "module"
},
"settings": {
"react": {
"version": "detect"
}
},
"plugins": ["react", "react-hooks"],
"rules": {
// NextJs specific fix: suppress errors for missing 'import React' in files for nextjs
"react/react-in-jsx-scope": "off",
// NextJs specific fix: allow jsx syntax in js files
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], //should add ".ts" if typescript project
"react/display-name": 1
}
}
Also, install ESLint extension for VSCode.
Reload VSCode window once to get proper linting
ESLint will automatically start detecting errors/warnings in *.js and *.jsx files. If that's not the case then either your project has no linting errors or ESLint is not properly setup.
To test if linting works run eslint command in terminal with folder path i.e. eslint pages/** and notice output.
To disable linting of some files/folders you can create a .eslintignore at the root of project.
.eslintignore:
# don't ever lint node_modules
node_modules
# don't lint build output (make sure it's set to your correct build folder name)
dist
# don't lint nyc coverage output
coverage
Finally, you can also add linting to scripts in package.json as a part of your build/deploy process:
"scripts": {
"lint": "eslint ./components/** ./pages/** -c .eslintrc.json --ext js,jsx",
"lint-fix": "eslint ./components/** ./pages/** -c .eslintrc.json --fix --ext js,jsx",
}
See my current ESLint configuration for NextJS Typescript project: https://github.com/GorvGoyl/Personal-Site-Gourav.io/blob/main/.eslintrc.js
you need to install required npm modules.
with Npm:
npm i -D babel-eslint eslint-config-airbnb eslint eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks
with Yarn:
yarn add -D babel-eslint eslint-config-airbnb eslint eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks
Here is related article about that
https://medium.com/#melih193/next-js-eslint-setup-tutorial-for-airbnb-config-c2b04183a92a
Official in-tree examples
As mentioned by GorvGoyl, some better integration was added around Next.js 11.
Although there is documentation at: https://nextjs.org/docs/basic-features/eslint being a eslint newbie I just couldn't understand what I was supposed to do, so I just looked under examples/ and found some actual working code:
examples/with-eslint
https://github.com/vercel/next.js/tree/v12.0.7/examples/with-eslint
Minimal eslint example.
The setup contains:
package.json
{
"name": "with-eslint",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"license": "MIT",
"dependencies": {
"next": "12.0.7",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"eslint": "^7.24.0",
"eslint-config-next": "12.0.7"
}
}
.eslintrc
{
"extends": "next",
"root": true
}
pages/index.js
const Home = () => (
<div>
<script src="https://fake-script.com" />
<p>Home</p>
</div>
)
export default Home
For example doing:
cd examples/with-eslint
npm install
npm run lint
gives the desired error:
3:5 Warning: External synchronous scripts are forbidden. See: https://nextjs.org/docs/messages/no-sync-scripts. #next/next/no-sync-scripts
We can modify pages/index.js a bit to add some more cases that we might want to fail:
import React from 'react'
const Home = () => {
let s = 'abc'
s = "abc"
let unused
if (false) {
React.useEffect(() => 1)
}
return (
<div>
<script src="https://fake-script.com" />
<p>Home</p>
</div>
)
}
export default Home
and the results are:
" vs ' on strings: unchecked
unused unused variable: unchecked
conditional React.useEffect: checked. I think this is because it includes the 'plugin:react-hooks/recommended', at: https://github.com/vercel/next.js/blob/v12.0.7/packages/eslint-config-next/index.js#L12
examples/with-typescript-eslint-jest
https://github.com/vercel/next.js/tree/v12.0.7/examples/with-typescript-eslint-jest
Exmple also with typescript.
Note that this example cannot be run in-tree otherwise it fails with:
ESLint couldn't find the plugin "eslint-plugin-jest".
which is must be picking up from repo toplevel:
The plugin "eslint-plugin-jest" was referenced from the config file in "../../.eslintrc.json#overrides[0]".
you have to first copy it outside somewhere like:
cp -rv examples/with-typescript-eslint-jest /tmp
cd /tmp/with-typescript-eslint-jest
But I think this examples is a bit outdated as it is not using the"
"extends": "next",
preset.
My recommended Next 12 typescript + prettier setup
Since the in-tree "examples/with-typescript-eslint-jest" doesn't look very up-to-date, here's a version of it that should be (just without jest):
package.json
{
"name": "with-eslint",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"lint": "next lint",
"format": "prettier --ignore-path .gitignore --write .",
"type-check": "tsc"
},
"license": "MIT",
"dependencies": {
"install": "0.13.0",
"next": "12.0.7",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"#types/node": "12.12.21",
"#types/react": "17.0.2",
"#types/react-dom": "17.0.1",
"eslint": "8.5.0",
"eslint-config-next": "12.0.7",
"eslint-config-prettier": "7.2.0",
"eslint-plugin-prettier": "4.0.0",
"prettier": "2.5.1",
"typescript": "4.5.4"
},
"prettier": {
"printWidth": 80,
"semi": false,
"singleQuote": true
}
}
.eslintrc.json
{
"extends": ["eslint:recommended", "next", "prettier"],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
tsconfig.json (autogenerated by Next when you run npm run dev)
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
.gitignore
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# vercel
.vercel
# typescript
*.tsbuildinfo
pages/index.tsx
import React from 'react'
const Home = () => {
let n: number
let s = 'abc'
s = "abc"
let unused
if (false) {
React.useEffect(() => 1)
}
return (
<div>
<script src="https://fake-script.com" />
<p>Home</p>
</div>
)
}
export default Home
With this setup doing:
npm run lint
catches all issues as we would like:
4:7 Error: 'n' is defined but never used. no-unused-vars
6:3 Error: 's' is assigned a value but never used. no-unused-vars
6:7 Error: Replace `"abc"` with `'abc'` prettier/prettier
7:7 Error: 'unused' is defined but never used. no-unused-vars
8:7 Error: Unexpected constant condition. no-constant-condition
9:5 Error: React Hook "React.useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render. react-hooks/rules-of-hooks
13:7 Warning: External synchronous scripts are forbidden. See: https://nextjs.org/docs/messages/no-sync-scripts. #next/next/no-sync-scripts
The prettier errors can be fixed automatically with autoformatting:
npm run format
which automatically patches for us:
--- a/pages/index.tsx
+++ b/pages/index.tsx
## -3,7 +3,7 ## import React from 'react'
const Home = () => {
let n: number
let s = 'abc'
- s = "abc"
+ s = 'abc'
let unused
if (false) {
Running:
npm run type-check
catches the type error:
pages/index.tsx:9:27 - error TS2322: Type 'number' is not assignable to type 'void | Destructor'.
9 React.useEffect(() => 1)
Both npm run lint and npm run type-check are automatically run by npm run build.
Lint is enabled only on pages/, components/ and lib/ by default
As mentioned at: https://nextjs.org/docs/basic-features/eslint#linting-custom-directories-and-files
To enable it everywhere in the projects:
module.exports = {
eslint: {
dirs: ['.'],
},
}

eslint-watch not running upon saving files with the .jsx extension

I installed eslint-watch https://www.npmjs.com/package/eslint-watch so eslint would run every time I hit save. However, whenever I save a file with the extension .jsx the linter doesn't run. I'm confident this is the issue because the linter does run after i save a change to a non jsx file and it works if I change the .jsx file extension to .js.
I would really appreciate any help. Here are the relevant files.
package.json scripts (directory paths are correct)
"lint": "esw webpack.config.* babel.config.* src/**/*.js src/**/*.jsx server/**/*.js --color",
"lint:watch": "npm run lint -- --watch",
package.json dependencies (same versions in package-lock.json)
"eslint": "^6.2.1",
"eslint-watch": "^6.0.0",
"eslint-plugin-react": "^7.14.3",
.eslintrc.js (in the root directory)
module.exports = {
"root": true,
"env": {
"browser": true,
"node": true,
"es6": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"plugins": [
"react"
],
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
},
"settings": {
"react": {
"version": "detect"
}
}
}
I think all you have to do is add the --ext .jsx flag. This will tell eslint to look for jsx extensions on run. Even though in your config you have told it to parse jsx files and you've passed the glob pattern for jsx, eslint doesn't know it needs to look for or parse .jsx files.
If this doesn't resolve your issue create a ticket on the repo's github page and I can assist further.

ESLint "Module build failed" error with eslint-config-airbnb

I am trying to set up a React project that uses webpack and ESLint with the airbnb config for ESLint. When I try starting up the project with webpack dev server, I get the following error:
"Module build failed: Error:
/react-template/node_modules/eslint-config-airbnb/rules/react-a11y.js:
ESLint configuration is invalid:
- Unexpected top-level property "ecmaFeatures"."
This is using eslint-config-airbnb v. 15.0.1. I checked the react-a11y.js file and confirmed there is a top-level property of "ecmaFeatures". I know as of ESLint 2.0.0 ecmaFeatures are now supposed to be under the parserOptions property, but I'm not sure if that only applies to the .eslintrc file. I'd like to use the airbnb config if possible, so I appreciate any assistance. Here is my .eslintrc file for reference.
.eslintrc
{
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2016,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"env": {
"es6": true,
"browser": true,
"node": true,
"jest": true
},
"extends": ["airbnb"]
}
I figured out a solution.
You have to edit react-a11y.js and react.js located in ./node_modules/.bin/eslint-config-airbnb/rules/.
In react-a11y.js remove:
ecmaFeatures: {
jsx: true
},
and replace it with:
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
In react.js just remove:
ecmaFeatures: {
jsx: true
},
and you should be good to go.
Also, I'm looking at the airbnb's repo right now and it looks like they fixed it almost a month ago, but I just reinstalled eslint-config-airbnb today, so I'm not sure what happened there.
Here are links to the react-a11y.js diff and the react.js diff. They show exactly what you need to add/remove.
Global eslint has been upgraded from 3.19.0-1 to 4.0.0-1 when the problem appeared for me.
eslint v4 is not yet supported in eslint-config-airbnb and eslint-config-airbnb-base
https://github.com/eslint/eslint/issues/8726#issuecomment-308367541
You JSON isn't valid. It's missing quotes around first "parser";
{
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2016,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"env": {
"es6": true,
"browser": true,
"node": true,
"jest": true
},
"extends": ["airbnb"]
}

Resources