jsx-eslint / eslint-plugin-react

React-specific linting rules for ESLint
MIT License
9.01k stars 2.77k forks source link

[Bug]: react/destructuring-assignment inconsistent behavior #3828

Closed moses-crasman closed 1 month ago

moses-crasman commented 2 months ago

Is there an existing issue for this?

Description Overview

Brief description

It appears the react/destructuring-assignment rule is not behaving consistently with type definitions.

Code example

type Props = { text: string };
export const MyComponent: React.FC<Props> = (props) => {
  return <div>{props.text}</div>;
  //           ^^^^^^^^^^
};

export const MyOtherComponent: React.FC<Props> = (props) => {
  const { text } = props;
  type MyType = typeof props.text;
  return <div>{text as MyType}</div>;
};

What is happening? / What is the error?

To me this appears as an unexpected inconsistency.

What command(s) did you run to reproduce issue?

Using the code example above;

npx eslint ./eslint-test.tsx

Expected Behavior

I would expect both components to trigger the linter rule.

eslint-plugin-react version

v7.34.3

eslint version

v8.57.0

node version

v18.20.2

ljharb commented 2 months ago

I can indeed reproduce this, even when both snippets define a Props type, infer typeof props.text, and as MyType.

ljharb commented 2 months ago

ok, so this is happening because the rule is counting props references, and in the second snippet, there's more than one, so it bails out.

If I comment out that propsRefs.length check, then the autofix fails to account for all of the other references, and that causes broken output.

I think the rule needs to be made smarter, by autofixing everything that references a property of props, but also not warning when there's any bare references to props that aren't destructuring it.