Saturday 29 May 2021

Max jsx props per line within a function parameter

I am using prettier-eslint and trying to add a new eslint rule that limits the number of jsx props per line:

eslintrc:

...
rules: {
  'react/jsx-max-props-per-line': [2, { maximum: 1 }],
  'react/jsx-indent-props': [2, 2],
  'react/jsx-first-prop-new-line': [2, 'multiline'],
}
...

However, when I have code like the following, it gets corrected as detailed below. I would prefer it to be corrected instead to the following. jsx-wrap-multiline seems to go after the solution I am looking for, but it doesn't deal with function parameters. How would I be able to get the desired linting linsted below? Thanks!

// Original Code
const foo = () => showModal(<SampleComponent title="hello world" id={123} />);

// Fixed Code
const foo = () =>
  showModal(<SampleComponent
    title="hello world"
    id={123}
  />);

// Desired Fix
const foo = () => showModal(
  <SampleComponent
    title="hello world"
    id={123}
  />
);

full .estlintrc.js:

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
  },
  env: {
    browser: true,
  },
  overrides: [
    {
      files: ['*.test.*'],
      env: {
        jest: true,
      },
    },
  ],
  plugins: ['@typescript-eslint', 'jsx-max-len', '@babel'],
  extends: [
    'airbnb-typescript',
    'plugin:@typescript-eslint/recommended',
    'plugin:react/recommended',
    'prettier',
    'prettier/react',
    'prettier/@typescript-eslint',
  ],
  globals: {
    // tests
    page: true,
    browser: true,
    describe: true,
    beforeAll: true,
    beforeEach: true,
    afterAll: true,
    afterEach: true,
    it: true,
    test: true,
    expect: true,
    global: true,
  },
  rules: {
    // ----- REACT ----- //
    'react/destructuring-assignment': 0,
    'react/display-name': 0,
    'react/jsx-closing-bracket-location': 1,
    'react/jsx-curly-newline': 0, // handled by prettier
    'react/jsx-indent': 'off',
    'react/jsx-one-expression-per-line': 0, // unnecessary rule
    'react/jsx-props-no-spreading': 0, // Allow prop spreading
    'react/jsx-wrap-multilines': ['error', { arrow: true, return: true, declaration: true }],
    'react/no-array-index-key': 0, // index keys are fine when used correctly
    'react/no-unused-prop-types': 0, // Fails on SFC which GoogleMapReact is, etc.
    'react/prop-types': 0, // Don't use prop types, use Typescript
    'react/require-default-props': 0,
    'react/jsx-max-props-per-line': [2, { maximum: 1 }],
    'react/jsx-indent-props': [2, 2],
    'react/jsx-first-prop-new-line': [2, 'multiline'],

    // ----- JSX ----- //
    'jsx-a11y/click-events-have-key-events': 0,
    'jsx-a11y/label-has-associated-control': 0,
    'jsx-a11y/label-has-for': 0, // good eventually, but not now
    'jsx-a11y/no-noninteractive-element-interactions': 0,
    'jsx-a11y/no-static-element-interactions': 0,
    'jsx-max-len/jsx-max-len': [2, { lineMaxLength: 100, tabWidth: 2, maxAttributesPerLine: 1 }],

    // ----- TYPESCRIPT ----- //
    '@typescript-eslint/ban-types': 0,
    '@typescript-eslint/explicit-module-boundary-types': 0, // Eventually turn these back on
    '@typescript-eslint/indent': 'off',
    '@typescript-eslint/no-empty-interface': 0,
    '@typescript-eslint/no-explicit-any': 0, // For now allow 'any'
    '@typescript-eslint/no-inferrable-types': 0,
    '@typescript-eslint/no-redeclare': 0,
    '@typescript-eslint/no-var-requires': 0,
    '@typescript-eslint/prefer-as-const': 0,
    '@typescript-eslint/prefer-optional-chain': 'error',

    // ----- OTHER ----- //
    'array-bracket-spacing': 0, // ['error', 'always'],
    'arrow-parens': ['error', 'always'],
    'comma-dangle': ['error', 'always-multiline'],
    // Always enforce curly braces around if/else blocks; https://eslint.org/docs/rules/curly
    curly: 'error',
    'import/named': 0, // doesn't play well with Typescript
    'implicit-arrow-linebreak': 0, // this conflicts with lines that are too long
    'import/prefer-default-export': 0,
    // This doesn't work with the aliases we've set up, plus I believe Typescript catches this
    // anyways
    'import/no-unresolved': 0,
    indent: 'off',
    'no-alert': 0,
    'no-case-declarations': 0,
    'no-console': ['error', { allow: ['warn', 'error'] }], // allow warnings and error logs
    'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
    // GraphQL relies on an internal variable, __typename, with a dangling underscore.
    'no-underscore-dangle': ['error', { allow: ['__typename'] }],
    // Use the babel/eslint plugin to handle optional changing something like a?.foo() would
    // raise a linting error before
    'no-unused-expressions': 0,
    // I *think* that the typescript compiler catches unused variables, plus this complaints about
    // imported types
    'no-unused-vars': 0,
    'object-curly-spacing': ['error', 'always'],
    'prefer-destructuring': 0,
    quotes: 'off',
    semi: ['error', 'always'],
  },
};

full .prettierrc:

{
  "arrowParens": "always",
  "printWidth": 100,
  "trailingComma": "all",
  "tabWidth": 2,
  "singleQuote": true
}


from Max jsx props per line within a function parameter

No comments:

Post a Comment