8

Our project is using Prettier and ESLint. Normally they work fine together, but we're running into an issue where the two are in conflict. I don't know why, I can't figure out how to fix it, and I can't disable prettier for the line because I get errors.

Relevant parts of our settings

// .prettierrc
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "trailingComma": "es5",
  "arrowParens": "always"

// eslintrc.js
  extends: ['airbnb', 'eslint-config-prettier', 'prettier/react'],
  plugins: [
    'eslint-plugin-prettier',
    'redux-saga',
    'react',
    'react-hooks',
    'jsx-a11y',
  ],
  rules: {
    'prettier/prettier': ['error'],
    indent: [
      2,
      2,
      {
        SwitchCase: 1,
      },
    ],
    'max-len': 0,

And here is the code, with comments added to indicate the issues:

    const options =
      children === undefined
        ? items.map((item) => (
          // Prettier complains about the next four lines
          <option key={uuidv1()} value={item}>
            {item}
          </option>
        ))
        : children;

Prettier wants those lines intended another two spaces.

Screenshot of errors

ESLint likes them where they are. I'm inclined to agree with ESLint. If I auto-format for Prettier, ESLint complains and wants it changed back. I am using VSCode. We haven't had such a conflict anywhere else in our code base.

I tried just disabling prettier for those lines, but the auto-disable option with eslint adds // eslint-disable-next-line prettier/prettier, which causes the app to error out with Definition for rule 'prettier/prettier' was not found. Trying to add // prettier-ignore is impossible because of the JSX.

I don't understand why Prettier wants what ESLint says it wants. The only way we've been able to fix it is by removing 'prettier/prettier': ['error'], from our ESLint config entirely, which doesn't seem appropriate.

Suggestions?

Update 10/10/19 - Thanks to a suggestion by user chazsolo, I modified how the function was formatted to get this, which doesn't have any linting issues:

const dropDownOptions =
  children ||
  items.map((item) => (
    <option key={uuidv1()} value={item.value || item}>
      {item.text || item}
    </option>
  ));

This is a viable workaround for this problem, but I'm leaving this question unanswered, as I still feel like my code is entirely valid and shouldn't get this conflict.

The workaround also only works if I'm checking a value like children for being falsey. We have another condition where it is a match, and I can't short-circuit it in the same way. All of these problems involve the use of .map().

// Can't short-circuit here
var === SOME_ENUM
  ? filteredItems.map((item) => (
      // some JSX
    ))
  : filteredItems.map((item) => (
      // some other JSX
    ));

I can move the condition inside the map function, but that leads to checking the condition every loop.

This problem has cropped up a lot, and I'll probably be creating an issue in Prettier for it at this rate, because it's rather annoying to troubleshoot.

cdpautsch
  • 1,769
  • 3
  • 13
  • 24
  • Are you opposed to writing your code a little differently? Instead of using a ternary you can short-circuit `children` and `items.map`. I can't verify if that will work? – chazsolo Oct 10 '19 at 17:35
  • See my edit. It's a good suggestion, and works for this case, but we're finding a lot of similar problems involving map inside ternary operators. Not every workaround is possible or ideal. :/ Still, appreciate the idea! – cdpautsch Oct 10 '19 at 20:05
  • Glad that one helped you out, but unfortunately I don't know the best way to let eslint/prettier work well together. In your next example I'd recommend making the inline mapping functions methods on the component, then using like `SOME_ENUM ? filteredItems.map(fn1) : filteredItems.map(fn2)`. I know it's not fixing the issue but something to do in the interim :) – chazsolo Oct 10 '19 at 20:17

1 Answers1

3

My basic setup is working well for vue/ts in .eslintrc.json. You should add prettier in plugins

{
  "parser": "vue-eslint-parser",
  "parserOptions": { 
    "parser": "@typescript-eslint/parser" 
  },
  "plugins": ["@typescript-eslint", "prettier"],
  "rules": {
    "semi": ["error", "never"],
    "quotes": ["error", "single"],
    "prettier/prettier": "error"
  }
}
bravohex
  • 966
  • 13
  • 21