eslint-plugin-react icon indicating copy to clipboard operation
eslint-plugin-react copied to clipboard

[New Rule] jsx-embed-condition

Open steelbrain opened this issue 4 years ago • 16 comments
trafficstars

This rule disallows use of && inside JSX Embeds to avoid conditional numbers from being rendered.

Fixes https://github.com/yannickcr/eslint-plugin-react/issues/1979

steelbrain avatar Dec 26 '20 14:12 steelbrain

I'm still not convinced this is a rule worth adding

It is a convention recommended by The official React docs. A whole bunch of people have been stung by this bug, many didn't even know what caused it, see:

  • https://github.com/facebook/react-native/issues/20764
  • https://github.com/facebook/react-native/issues/23607
  • https://github.com/facebook/react-native/issues/23735
  • https://github.com/artsy/emission/pull/1706
  • https://blog.echobind.com/a-common-conditional-rendering-bug-in-react-native-8bbbc400abd8

(and you'll find many more examples by searching for "Text strings must be rendered within a Text component" on Google)

Apart from crashing React Native hard, the bug is known to add random 0s to the DOM in HTML renderer. I wrote this PR because my team got bit by this a few times.

If it were added, it'd need autofix to avoid being too disruptive.

This Lint rule is opt-in only. I can commit to adding an autofix for it later next month. My work schedule is pretty tight before that.

you can specify the parserOptions.ecmaVersion to be 2020 in this test case.

Doing so fixed the check on tests for latest Node.js runners, but broke them on the rest. I looked around the repository and couldn't find any tests with ecmaVersion newer than 2018. I would appreciate some help here! Thanks!

steelbrain avatar Dec 27 '20 01:12 steelbrain

You can pass parserOptions.ecmaVersion directly in the one test case.

ljharb avatar Dec 29 '20 00:12 ljharb

You can pass parserOptions.ecmaVersion directly in the one test case.

Attempted in https://github.com/yannickcr/eslint-plugin-react/pull/2888/commits/8abb5dcd900845d416f4469d7fc2fbf9197c4040 No dice. Any other ideas?

steelbrain avatar Dec 29 '20 02:12 steelbrain

Please mark the PR as ready for review once the next round of changes is done. Thanks!

ljharb avatar Dec 30 '20 00:12 ljharb

We have a similar rule in an internal codebase called logical-and-expressions; its existence in our jsx-ruleset makes it clear what its scope is.

Since this plugin's purview is a bit broader, perhaps a name like jsx-logical-and-expressions would capture the rule's scope+spirit.

duncanbeevers avatar Jan 04 '21 01:01 duncanbeevers

@steelbrain Here's the internal rule we use, which includes a simple fixer.

module.exports = {
  meta: {
    docs: {
      url: 'SECRET URL'
    },
    fixable: 'code'
  },
  create(context) {
    const sourceCode = context.getSourceCode();

    return {
      JSXExpressionContainer(node) {
        if (
          node.expression.type === 'LogicalExpression' &&
          node.expression.operator === '&&' &&
          node.parent.type !== 'JSXAttribute'
        ) {
          context.report({
            node,
            message: 'JSX expression should not use logical-and.',
            fix: (fixer) => fixer.replaceText(
              node,
              `{${sourceCode.getText(node.expression.left)} ? ${sourceCode.getText(node.expression.right)} : null}`
            )
          });
        }
      }
    };
  }
};

duncanbeevers avatar Jan 04 '21 19:01 duncanbeevers

I do not have the bandwidth to work on it this week, I'll continue this work on the weekend. Thank you for your continued support!

steelbrain avatar Jan 04 '21 19:01 steelbrain

We've also been bit by this bug and would like to see this rule enforced in our code base

Dakuan avatar Dec 07 '21 15:12 Dakuan

Are these changes still active? Would love to have this rule

wu-json avatar Jun 29 '22 15:06 wu-json

@steelbrain are you still planning to finish this?

ljharb avatar Jun 29 '22 17:06 ljharb

@ljharb Happy to open up a new PR with the lint rule + fix + tests if ya'll are interested in this. I was gonna release it as a separate package otherwise.

frolic avatar Jun 29 '22 21:06 frolic

I do not have the bandwidth in the near future and this needs more love than I can give right now :) Good luck @holic

steelbrain avatar Jun 29 '22 23:06 steelbrain

Let's please keep this open so it can be reused.

ljharb avatar Jun 29 '22 23:06 ljharb

@holic please post a branch link here, and i'll update the PR

ljharb avatar Jun 29 '22 23:06 ljharb

Added a PR here: https://github.com/jsx-eslint/eslint-plugin-react/pull/3318

This ports over the code we used internally at my last company that I was intending to release as its own package. Let me know if you'd prefer I build off of this PR instead.

frolic avatar Jul 02 '22 17:07 frolic

@holic i thought i was pretty clear i did not want a second PR opened; that pollutes the repo forever. Now I have to keep both PRs open and in sync until both are landed together.

ljharb avatar Jul 02 '22 21:07 ljharb

Closed by https://github.com/jsx-eslint/eslint-plugin-react/pull/3203

steelbrain avatar Dec 20 '22 07:12 steelbrain