airbnb / javascript

JavaScript Style Guide
MIT License
145.07k stars 26.5k forks source link

How to configure React Native (Expo) project to use AirBnB's React rules via ESLint? #1589

Closed superKalo closed 6 years ago

superKalo commented 7 years ago

I simply want to set-up the AirBnb's React (Native) rules via ESLint on a React Native (Expo) project.

I found a ton of contradictory articles how to do that and I got really frustrated. Are there any official set-up guidelines?

Which modules exactly do I need to install with npm and how should my .eslintrc config look like?

PS: Could somebody please add a "question" tag to this issue?

amackintosh commented 6 years ago

This is what I do in React and React Native:

Step 1

npm install --save-dev eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-react eslint-plugin-jsx-a11y babel-eslint

Step 2 Backup your eslintrc file in case you want to examine it.

Step 3

eslint --init
  1. Select 'Use a popular style guide'
  2. Select Airbnb
  3. Select your options, pick JSON type (.eslintrc is the old filename based on my research, but it's the same thing)
  4. Allow it to update newer versions and/or install packages if it asks

Step 4 Restart your editor

Step 5 Paste this into your .eslintrc.json: and remove my comments which will cause the JSON to blow up

{
    "env": {
        "node": true, // this is the best starting point
        "browser": true, // for react web
        "es6": true // enables es6 features
    },
    "parser": "babel-eslint", // needed to make babel stuff work properly
    "extends": "airbnb"
}

If there are expo eslint settings, they will fit on top of these.

I collected these settings over time, mostly from researching specific JSX and babel related errors and reading.

I'm posting it because no one else has helped you in the past month, and this works. We can now switch the question from, "what is the correct way?", to the more easy to handle "is this not the correct way?"

superKalo commented 6 years ago

Thank you, @amackintosh ! <3

ljharb commented 6 years ago

@amackintosh I've removed your custom rules (since they're not relevant to your answer) and also all the redundant stuff, which included all the "plugins" declarations, sourceType, and parserOptions, all of which the airbnb config specifies already.

marsonmao commented 6 years ago

@amackintosh I've done the same with you, but I can't identify __DEV__ as a valid global variable. I think this one should be valid since it is listed in the official document [here]. Not sure if anyone got some clues how to fix this issue? I tried adding globals in .eslintrc but don't think it's the correct way.

ljharb commented 6 years ago

@marsonmao That is indeed the correct way; also that document is for react-native, and not for JS or react overall.

marsonmao commented 6 years ago

@ljharb Thanks. I think you're right since I found the .eslintrc file of react native, and it adds __DEV__ in globals there.

And I know the doc I mentioned is for react-native, but this issue was related so I wrote the question, hope that was proper.

mostafa-drz commented 6 years ago

(Just a quick note on the solution mentioned here) The config @amackintosh shared here works very well for me, but I got the error [eslint] JSX not allowed in files with extension '.js' (react/jsx-filename-extension) (because I use some helper functions in my components for rendering out of the render function of component), I solved this problem by what mentioned here, so my .eslintrc.json is: { "env": { "node": true, "browser": true, "es6": true }, "parser": "babel-eslint", "extends": "airbnb", "rules": { "react/jsx-filename-extension": [ 1, { "extensions": [ ".js", ".jsx" ] } ] } } and everything is working perfect

gitsad commented 6 years ago

I have just started a project in the react native with expo and I wonder if it's possible to lint the code on expo reload. On web we have webpack and eslint-loader. I know that I can eject the app and build react with haul or with something else and probably after that inject some eslint plugin to handle lint on hot reload. Is there any way to handle something like this in react native with expo without ejecting ?

crj92 commented 6 years ago

@amackintosh , Hi and thanks for the steps you have provided. I have used the same for CRNA and RN projects, but it is not working for expo projects. At step 1, it installs those package but removes 500+ packages, which in turn starts throwing error on many libraries being not included. Please suggest something.

mhulse commented 6 years ago

Not sure if this helps anyone else, but due to the local install, I had to add eslint as an npm script to my package.json:

"scripts": {
  "eslint": "eslint"
}

And then:

$ npm run eslint -- --init
007arunwilson commented 6 years ago

@amackintosh (y) But for me it worked like ./node_modules/.bin/eslint --init

aurelienbouteiller commented 6 years ago

There is also "npx" which can be useful here. It allows to only write

npx eslint

when it’s installed in local. https://github.com/zkat/npx/

agm1984 commented 6 years ago

I can't edit my comment now and of course mind blown that I just helped myself in the future after I forgot all this. 🀣

I just noticed jest is missing from the env declaration. You can add it there to get rid of the red splatter in your test files. Here it is added to what is shown above:

    "env": {
        "node": true,
        "browser": true,
        "es6": true,
        "jest": true
    },
calendee commented 6 years ago

@gitsad Did you ever find a solution to this? I'd like the Metro Bundler to automatically run eslint on each reload.

xavierartot commented 6 years ago

I have a config for react-native:

  parser: 'babel-eslint',
  parserOptions: {
    "ecmaVersion": 6,
    allowImportExportEverywhere: false,
    ecmaFeatures: {
      jsx: true,
    },
  },
  plugins: ['react', 'react-redux', ],
  extends: ['airbnb',
  // "eslint:recommended"
  'plugin:react/recommended', 'plugin:react-redux/recommended', ],
  rules: {
    'no-debugger': 0,
    'import/no-named-as-default': 0,
    'react/jsx-indent': [2, 2], // error & 2 spaces
    'react/jsx-indent-props': [2, 2],
    'react/prefer-stateless-function': 0,
    'react/jsx-filename-extension': 0,
    'react/no-unused-state': 1,
    'jsx-a11y/anchor-is-valid': 1,
    'no-unused-vars': 1,
    quotes: [2, 'single'],
    'react/jsx-quotes': 1,
    'class-methods-use-this': 0,
    'no-console': 0,
    'no-return-assign': 1,
    semi: ['error', 'never'],
    'react/jsx-key': 2,
    'react/jsx-closing-tag-location': 2,
    'react/no-access-state-in-setstate': 2,
    'react/button-has-type': 2,
    'react/jsx-sort-props': 2,

    // configure when I have time
    'react/display-name': 1,
    'react/forbid-prop-types': 1,
    'react/jsx-boolean-value': 1,
    'react/jsx-closing-bracket-location': 1,
    'react/jsx-curly-spacing': 1,
    'react/jsx-handler-names': 1,
    'react/jsx-max-props-per-line': 1,
    'react/jsx-no-bind': 1,
    'react/jsx-no-duplicate-props': 1,
    'react/jsx-no-literals': 1,
    'react/jsx-no-undef': 1,
    'react/jsx-pascal-case': 1,
    'react/jsx-sort-prop-types': 1,
    'react/jsx-sort-props': 1,
    'react/jsx-uses-react': 1,
    'react/jsx-uses-vars': 1,
    'react/no-danger': 1,
    'react/no-did-mount-set-state': 1,
    'react/no-did-update-set-state': 1,
    'react/no-direct-mutation-state': 1,
    'react/no-multi-comp': 1,
    'react/no-set-state': 1,
    'react/no-unknown-property': 1,
    'react/prefer-es6-class': 1,
    'react/prop-types': 1,
    'react/react-in-jsx-scope': 1,
    'react/require-extension': 1,
    'react/self-closing-comp': 1,
    'react/sort-comp': 1,
    'react/wrap-multilines': 1,
  },
}
Asday commented 5 years ago

@gitsad @calendee did either of you figure out how to get it working? No combination of "eslint" and "metro" yields anything useful from google...

16oh4 commented 4 years ago

@gitsad @calendee did either of you figure out how to get it working? No combination of "eslint" and "metro" yields anything useful from google...

I am looking to do the same thing!! I have researched for hours and no luck.

Asday commented 4 years ago

@16oh4 I'm neck deep in a home move right now, do you wanna give me a poke in a week? I can show you roughly what I did, then.

calendee commented 4 years ago

@gitsad @calendee did either of you figure out how to get it working? No combination of "eslint" and "metro" yields anything useful from google...

Nope. I think I gave up. Sorry.

pcy8282 commented 4 years ago

νš¨γ…› μ²­μ†Œν•˜λŠ” γ…‹γ……4γ……γ…Žγ……γ…Š2ctcs vax ,cvvgx,γ…Œγ…Žγ…Š,γ„±γ…Žγ…Žγ…Žγ„΄γ„΄γ„΄γ„·γ„·γ…‡%=-ㅅㅋㅍㅋ4

2020λ…„ 4μ›” 8일 (수) 08:18, Justin Noel notifications@github.comλ‹˜μ΄ μž‘μ„±:

@gitsad https://github.com/gitsad @calendee https://github.com/calendee did either of you figure out how to get it working? No combination of "eslint" and "metro" yields anything useful from google...

Nope. I think I gave up. Sorry.

β€” You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/airbnb/javascript/issues/1589#issuecomment-610665384, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKQRSEWHXLFMUB6JKSH3VS3RLOYDXANCNFSM4D63366Q .

tibbus commented 4 years ago

@Asday do you have eslint working inside metro?

Asday commented 4 years ago

I do not. I have two terminal windows - one for metro (grumble grumble grumble), and one for jest, which I have running everything else.

An abbreviated version of my package.json:

{
  "scripts": {
    "jest:watch": "jest --watch --changedSince=origin/master"
  },
  "devDependencies": {
    "eslint": "5.16.0",
    "eslint-config-airbnb": "17.1.0",
    "eslint-plugin-import": "2.17.2",
    "eslint-plugin-jsx-a11y": "6.2.1",
    "eslint-plugin-react": "7.12.4",
    "eslint-plugin-simple-import-sort": "3.1.0",
    "jest-expo": "33.0.1",
    "jest-matcher-utils": "24.7.0",
    "jest-runner-eslint": "0.7.5"
  },
  "jest": {
    "projects": [
      {
        "displayName": "test",
        "preset": "jest-expo",
        "transform": {
          "^.+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp|ttf|otf|m4v|mov|mp4|mpeg|mpg|webm|aac|aiff|caf|m4a|mp3|wav|html|pdf|obj)$": "jest-expo/src/preset/assetFileTransformer.js",
          "^.+\\.(jsx?|tsx?)$": "babel-jest"
        },
        "transformIgnorePatterns": [
          "node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|sentry-expo|native-base|redux-persist-expo-securestore)"
        ]
      },
      {
        "runner": "jest-runner-eslint",
        "displayName": "lint",
        "testMatch": [
          "**/*.js",
          "**/*.jsx"
        ]
      }
    ]
  }
}

Then I can run npm run jest:watch, and it'll behave relatively nicely.

darrenangle commented 3 years ago

I found this flow useful: https://dev.to/yovanylg/the-easiest-way-to-begin-with-expo-typescript-eslint-and-prettier-3dj1

Asday commented 3 years ago

@Asday do you have eslint working inside metro?

Gave up completely.

AhmedAbuelenin commented 1 month ago

This helped me as well. https://gist.github.com/yovany-lg/104ed47e74d1ba64f68d79a3e5f76e91