Skip to content

The offset for React component body depends on component name length in v2.3 #10848

@kachkaev

Description

@kachkaev

Prettier 2.3.0
Playground link

--parser typescript

After switching from Prettier 2.2.1 to 2.3.0 in a large React + TS codebase, I've noticed an unexpectedly large diff. The offset for many React components has shifted.

It turns out that the length of the component name now affects the location of ({. If these opening brackets are moved to the new line, the whole component body is shifted. This makes git diffs quite fragile.

Imagine renaming some component during a refactor. In Prettier 2.2.1, the diff would be just one line but in Prettier 2.3.0, git blame for the whole file would end up broken.

Input:

interface MyComponentProps {
  x: number
}

const MyComponent: React.VoidFunctionComponent<MyComponentProps> = ({ x }) => {
  const a = useA()
  return <div>x = {x}; a = {a}</div>
}

interface MyComponent2Props {
  x: number
  y: number
}

const MyComponent2: React.VoidFunctionComponent<MyComponent2Props> = ({ x, y }) => {
  const a = useA()
  return <div>x = {x}; y = {y}; a = {a}</div>
}

interface MyComponentWithLongNameProps {
  x: number
  y: number
}

const MyComponentWithLongName: React.VoidFunctionComponent<MyComponentWithLongNameProps> = ({ x, y }) => {
  const a = useA()
  return <div>x = {x}; y = {y}; a = {a}</div>
}

Output:

interface MyComponentProps {
  x: number;
}

const MyComponent: React.VoidFunctionComponent<MyComponentProps> = ({ x }) => {
  const a = useA();
  return (
    <div>
      x = {x}; a = {a}
    </div>
  );
};

interface MyComponent2Props {
  x: number;
  y: number;
}

const MyComponent2: React.VoidFunctionComponent<MyComponent2Props> = ({
  x,
  y,
}) => {
  const a = useA();
  return (
    <div>
      x = {x}; y = {y}; a = {a}
    </div>
  );
};

interface MyComponentWithLongNameProps {
  x: number;
  y: number;
}

const MyComponentWithLongName: React.VoidFunctionComponent<MyComponentWithLongNameProps> =
  ({ x, y }) => {
    const a = useA();
    return (
      <div>
        x = {x}; y = {y}; a = {a}
      </div>
    );
  };

Expected behavior:

All three useA() and return statements have only two leading spaces, i.e. the offset does not depend on the component name length.

Our team will be staying on Prettier 2.2.1 in the meantime. Happy to help with a PR if we come up with some solution!

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:assignmentslang:typescriptIssues affecting TypeScript-specific constructs (not general JS issues)status:needs discussionIssues needing discussion and a decision to be made before action can be taken

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions