question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Indentation: JSX child element multiline prop gets unexpected extra indentation level

See original GitHub issue

Tell us about your environment

  • ESLint Version: 5.6.0
  • Node Version: 9.8.0
  • npm Version: 5.6.0

What parser (default, Babel-ESLint, etc.) are you using? Babel-ESLint

Please show your full configuration:

Configuration
{
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true
    },
    "extends": "eslint:recommended",
    "parser": "babel-eslint",
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "sourceType": "module"
    },
    "plugins": [
        "babel",
        "react"
    ],
    "rules": {
        "indent": [ "error", 4 ],
        "indent-legacy": "off",
        "jsx-quotes": [ "error", "prefer-double" ]
    }
}

What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.

export default <test prop={
    null
}><inner prop={
    null
} /></test>;
node_modules/.bin/eslint test.jsx

What did you expect to happen? No errors

What actually happened? Please include the actual, raw output from ESLint.

$ node_modules/.bin/eslint test.jsx

/path/to/project/test.jsx
  4:1  error  Expected indentation of 8 spaces but found 4  indent
  5:1  error  Expected indentation of 4 spaces but found 0  indent

✖ 2 problems (2 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

My initial encounter with this behaviour was with more complex use cases (JSX function-as-a-child pattern) but the above sample syntax is the simplest one that still triggers the indentation error.

In comparison, the following JSX syntax does not trigger the indentation error:

export default <test prop={null}><inner prop={
    null
} /></test>;

Looking at indent.js, I think the place that effects this result is the JSX element handler:

// ...
            JSXElement(node) {
                if (node.closingElement) {
                    addElementListIndent(node.children, sourceCode.getFirstToken(node.openingElement), sourceCode.getFirstToken(node.closingElement), 1);
                }
            },
// ...

The children of an element are expected to be 1 level in, relative to the starting token of the opening tag - which is the <. However, if the child starts on the same line as the opening tag, that offset is nullified (per logic in getDesiredIndent(token) function).

This is why the second JSX example does not trigger the indentation error - the inner element starts on same line as the starting < of the outer element. But in the first JSX example the inner element is no longer on the same line as the outer element’s < token, and that makes the lint rule expect one more indentation level for the inner element’s prop value.

The obvious workaround is to just put <inner ... /> on a new line and indent it. But it feels like using the starting < as indentation offset reference is a bit too simplistic? Just doesn’t feel completely “right”; also, we use a lot of function-as-a-child syntax and it would help save on indentation levels.

In my tests, I changed the JSX element handler logic to use the last token of the opening tag (i.e. the > that immediately precedes the contents), and that worked really well. If the child literal or expression starts on a new line, then the indentation level is increased by one as intended, but if it is on the same line, then the offset gets correctly ignored and the inner multiline props do not trigger the indentation error.

However, there is a problem with that approach - in some style guides, the opening tag’s > is expected to be indented relative to the <: i.e the react/jsx-closing-bracket-location rule with props-aligned setting. Thus, the following code would be valid but still trip up indent if the > is used as offset reference:

export default <test
    prop={null}
    >
    Some content
</test>;

I am not sure how many folks are using that convention - the indent rule actually “fights” it anyway as is - but that is still a caveat.

Thoughts? If there is a configuration option that might apply, happy to try it.

Thanks!

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
unframeworkcommented, Aug 16, 2019

Folks, this turned out to be not enough of a priority to put out a polished-enough fix on my end - I just got used to a more indent-heavy code style anyway. Thanks for helping discuss this!

0reactions
platinumazurecommented, Dec 23, 2018

Yes, we can reopen this, no worries. Thanks for your interest!

Read more comments on GitHub >

github_iconTop Results From Across the Web

ESLint Extra Parentheses In JSX - reactjs - Stack Overflow
I've noticed that extra parentheses are getting added to my multi-line conditional renders using logical AND (&&) in my jsx files.
Read more >
Ruby Style Guide
Use two spaces per indentation level (aka soft tabs). # bad - four spaces def some_method ... Align the elements of array literals...
Read more >
Available rules - eslint-plugin-vue
Rule ID Description vue/multi‑word‑component‑names require component names to be always multi‑word... vue/no‑arrow‑functions‑in‑watch disallow using arrow functions to define watcher... vue/no‑computed‑properties‑in‑data disallow accessing computed properties in data...
Read more >
eslint-plugin-react - npm
Otherwise, install it locally. $ npm install eslint-plugin-react --save-dev. Configuration. Use our preset to get reasonable defaults:.
Read more >
enforce consistent indentation (indent) - ESLint - Breword 文档集合
"ArrayExpression" (default: 1) enforces indentation level for elements in arrays. ... set to 0 will indent the multi-line property chains with 0 spaces....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found