Skip to content

Enforce explicit return statements in arrow functions #3948

@kachkaev

Description

@kachkaev

I would like to propose a change to react/function-component-definition or a new adjacent rule.

When a component is defined as an arrow function, we can choose to use a shorthand to omit the return keyword:

const ComponentA = () => {
  return (
    <Wrapper>
      <Greeting>hello</Greeting>
    </Wrapper>
  );
};

const ComponentB = () => (
  <Wrapper>
    <Greeting>hello</Greeting>
  </Wrapper>
);

The second example may look more attractive in the beginning because is looks less ‘bureaucratic’. However, the first example ends up being much easier to change. Let's look at the diff in each case if we decide to call a hook:

  const ComponentA = () => {
+   const hello = useTranslation("hello");
+
    return (
      <Wrapper>
-       <Greeting>hello</Greeting>
+       <Greeting>{hello}</Greeting>
      </Wrapper>
    );
  };

- const ComponentB = () => (
-   <Wrapper>
-     <Greeting>hello</Greeting>
-   </Wrapper>
- );
+ const ComponentB = () => {
+   const hello = useTranslation("hello");
+
+   return (
+     <Wrapper>
+       <Greeting>{hello}</Greeting>
+     </Wrapper>
+   );
+ };

As you can see, explicit return has allowed more of the lines to ‘survive’. When JSX in the original component is quite massive, adding even a single hook (and explicit return) may create a diff that's pretty hard to digest. It also worsens git blame so it's best to prevent the situation from the start.

It'd be great to have a rule that discourages arrow function shorthands in React components. Maybe it can be a part of the existing rule, not sure.

In the meantime, I am using no-restricted-syntax to mitigate the issue:

{
  "rules": {
    "no-restricted-syntax": [
      {
        "...": "..."
      },
      {
        "selector": "VariableDeclarator > ArrowFunctionExpression > JSXElement, VariableDeclarator > ArrowFunctionExpression > JSXFragment",
        "message": "Please avoid arrow function shorthand like `(...) => <Jsx />`. Replace it with `(...) => { return <Jsx /> }`. Explicit `return` allows calling hooks later on without producing massive git diffs."
      }
    ]
  }
}

It works but cannot have an auto-fix. I guess it’s better to have an official rule instead of an arbitrary AST selector. WDYT folks?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions