javascript: `react/function-component-definition` configuration violates style guide

In eslint-config-airbnb@19.0.0 (specifically https://github.com/airbnb/javascript/commit/1bc8cabd447ef9ce69d27ae70e67eb47daeffc21), react/function-component-definition was configured to allow only function expressions for named components:

https://github.com/airbnb/javascript/blob/1bc8cabd447ef9ce69d27ae70e67eb47daeffc21/packages/eslint-config-airbnb/rules/react.js#L526-L531

This has the effect of disallowing function declarations:

function Foo() {
  return <div />
}

While allowing only this style:

const Foo = function () {
  return <div />
}

This seems like a configuration mistake, as the React style guide consistently uses function declarations for components (as does the ecosystem as a whole) and specifically points out that “relying on function name inference is discouraged”. Let me know if you agree and I’ll PR a fix.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 36
  • Comments: 29 (1 by maintainers)

Commits related to this issue

Most upvoted comments

@slifty yes, it will be corrected soon. btw that seems like a lot of people going to the wrong place; stack overflow isn’t the place to report problems with any software. As far as this issue can tell, there’s only 12 people, not thousands.

The default rule keeps forcing me to use this

function HelloWorld() {
  return <h1>Hello World</h1>
}

instead of this

const HelloWorld = () => {
  return <h1>Hello World</h1>
}

And It no longer suggests the implicit return for arrow functions.

Using the following versions:

{
   ...
   "eslint": "^8.6.0",
   "eslint-config-airbnb": "^19.0.4",
   ...
}

re the changelog, I’ll try to do a better job highlighting breaking changes in future releases.

Why? For a number of reasons:

  • debugging. arrow functions can never have explicit names, only implicit ones via ES6 name inference, which can be unintuitive and surprisingly missing at times. Consider when you have export const Foo = (props) => {}; and then refactor that to be export const Foo = React.memo((props) => {}) - your “Foo” name suddenly vanishes, because you were relying on inference, probably without realizing it.
  • conceptual mismatch. arrow functions are conceptually meant to replace inline callbacks. They are not a general-purpose function replacement, even though they obviously can be used as such. An arrow function doesn’t properly convey the importance/noun-ness of a react component.

See also:

@ljharb In earlier versions there is no such problem when writing components using arrow-functions.

@namlq93 for example you can use in rules:

  rules: {
    // not sure if this is a "bug" or "feature" in airBnB config? https://github.com/airbnb/javascript/issues/2505
    'react/function-component-definition': [
      'error',
      {
        namedComponents: ['function-declaration', 'arrow-function'],
      },
    ],

@vicasas yes, and I’ll do a better job with the changelog next time. The change would have happened either way - the guide has never permitted arrow function components.

Dan’s tweets mean that if you use arrow components, you have to keep a lot more JS trivia in your head about name inference.

@ljharb I understand. I join the suggestion of @mryechkin about being able to show or warn about these changes to take them into account. The guide is so long that it is very difficult to learn each of the rules, which is why many developers trust the plugin 100%.

Reviewing the tweets, Dan Abramov indicates that it is equally valid to use arrow-functions to declare components, the important thing is that it is named.

Wanted to check: will this end up being corrected at some point?

There are a few thousand folks who seem to be facing issues when trying to write react under the current (9.x) version of the styleguide (this rule combined with rules against anonymous functions results in pretty verbose / un-intuitively repetitive component definitions).

The default rule keeps forcing me to use this

function HelloWorld() {
  return <h1>Hello World</h1>
}

instead of this

const HelloWorld = () => {
  return <h1>Hello World</h1>
}

And It no longer suggests the implicit return for arrow functions.

Using the following versions:

{
   ...
   "eslint": "^8.6.0",
   "eslint-config-airbnb": "^19.0.4",
   ...
}

How can I turn off this rule? I want to use function-declaration or arrow-function both are acceptable.

@mahyarmirrashed that understanding is not correct. This guide does not allow components to be arrow functions, so you’d have to override the rule definition to permit them.

@ljharb Awesome thank you (and for all the amazing work you do).

I hear you on the StackOverflow concern! Next time I see this kind of scenario I’ll more explicitly suggest commenting on the relevant issue in the answer.

Oops, I searched for existing issues but not PRs. One is already open to fix this: https://github.com/airbnb/javascript/pull/2501.