Giter Club home page Giter Club logo

eslint-react's Issues

[bug] `no-missing-component-display-name` not work with early return component

Describe the bug

The following code should not report an error

import { forwardRef, ReactNode } from 'react';

interface Props {
  children?: ReactNode;
}
export type Ref = HTMLButtonElement;

const FancyButton = forwardRef<Ref, Props>((props, ref) => {
  // It's works without this
  if (!props.children) return null;
  return (
    <button ref={ref} className="MyClassName" type="button">
      {props.children}
      hell
    </button>
  );
});

FancyButton.displayName = 'FancyButton';

export default function App() {
  return <FancyButton />;
}
/home/projects/vitejs-vite-bngjjk/src/app.tsx
  8:44  warning  no missing display name  @eslint-react/react/no-missing-component-display-name

✖ 1 problem (0 errors, 1 warning)

Reproduction

https://stackblitz.com/edit/vitejs-vite-bngjjk?file=src%2Fapp.tsx

Expected behavior

No response

Platform and versions

In stackblitz with "@eslint-react/eslint-plugin": "^0.8.9"

Stack trace

No response

Additional context

No response

[Rule Request] `react-hooks/ensure-use-memo-has-non-empty-deps`

Describe the problem

Describe the problem

const Comp = () => {
  const style = useMemo((theme: MantineTheme) => ({
    input: {
      fontFamily: theme.fontFamilyMonospace
    }
  }), []);
  return <Button sx={style} />
}

The useCallback here is completely not necessary, it can be hoisted:

const style = (theme: MantineTheme) => ({
  input: {
    fontFamily: theme.fontFamilyMonospace
  }
});

const Comp = () => {
  return <Button sx={style} />
}

Describe the solution you'd like

Find all useMemo hook inside components, and check if their dependency array has 0 elements.

Alternatives considered

No response

Additional context

No response

[Rule Migration] migrate eslint-plugin-react rules

Migration Status

Correctness and best practices rules

  • react/jsx-boolean-value ···················-> @eslint-react/jsx/prefer-shorthand-boolean
  • react/jsx-fragments ·······················-> @eslint-react/jsx/prefer-shorthand-fragment
  • react/jsx-key -----------|··················-> @eslint-react/jsx/no-missing-key
  • react/no-array-index-key |··················-> @eslint-react/jsx/no-array-index-key
  • ·························|··················-> @eslint-react/jsx/no-duplicate-key
  • -------------------------|··················-> @eslint-react/jsx/no-spreading-key
  • #102
  • react/jsx-no-useless-fragment ·············-> @eslint-react/jsx/no-useless-fragment
  • react/jsx-no-leaked-render ················-> @eslint-react/jsx/no-leaked-conditional-rendering
  • #104
  • react/jsx-no-comment-textnodes ············-> @eslint-react/jsx/no-comment-textnodes
  • react/jsx-filename-extension ··············-> @eslint-react/naming-convention/filename-extension
  • react/boolean-prop-naming ·················-> @eslint-react/naming-convention/boolean-prop
  • react/jsx-handler-names ···················-> @eslint-react/naming-convention/handler-prop
  • #205
  • #107
  • react/jsx-no-script-url ···················-> @eslint-react/react/no-script-url
  • react/jsx-no-target-blank ·················-> @eslint-react/react/no-unsafe-target-blank
  • react/button-has-type ·····················-> @eslint-react/react/no-missing-button-type
  • react/iframe-missing-sandbox | ············-> @eslint-react/react/no-missing-iframe-sandbox
  • -----------------------------|··············-> @eslint-react/react/no-unsafe-iframe-sandbox
  • react/jsx-no-constructed-context-values ···-> @eslint-react/react/no-constructed-context-value
  • react/no-danger ···························-> @eslint-react/react/no-dangerously-set-innerhtml
  • react/no-danger-with-children ·············-> @eslint-react/react/no-dangerously-set-innerhtml-with-children
  • react/no-namespace ························-> @eslint-react/react/no-namespace
  • #186
  • #173
  • #183
  • #185
  • react/no-string-refs ········|··············-> @eslint-react/react/no-string-refs
  • -----------------------------|··············-> @eslint-react/react/no-create-ref
  • #101
  • #202
  • #190
  • #191
  • #192
  • #197
  • #198
  • #199
  • #187
  • react/no-object-type-as-default-prop ······-> @eslint-react/react/no-unstable-default-props
  • react/no-unstable-nested-components ·······-> @eslint-react/react/no-unstable-nested-components
  • react/no-unused-state ·····················-> @eslint-react/react/no-unused-state
  • #207
  • react/void-dom-elements-no-children ·······-> @eslint-react/react/no-children-in-vold-dom-elements
  • react/destructuring-assignment ············-> @eslint-react/react/prefer-destructuring-assignment
  • react/prefer-read-only-props ··············-> @eslint-react/react/prefer-readonly-props
  • #301
  • #234

The following can be enforced by TypeScript, no need to implement them

  • react/jsx-no-duplicate-props
  • react/jsx-no-undef
  • react/jsx-uses-react
  • react/jsx-uses-vars
  • react/no-invalid-html-attribute
  • react/no-this-in-sfc
  • react/no-unescaped-entities -> No need when using @typescript-eslint/parser
  • react/no-unknown-property
  • react/style-prop-object
  • react/prop-types
  • react/react-in-jsx-scope
  • react/require-render-return

Customized rules

These rule will be added in the future.

  • react/forbid-elements -> @eslint-react/react/ban-components
  • react/forbid-component-props -> @eslint-react/react/ban-component-props
  • react/forbid-dom-props
    • -> @eslint-react/react/ban-html-props
    • -> @eslint-react/react/ban-svg-props

Stylistic rules

Stylistic rules are not supported by this plugin. Use dprint or @stylistic instead.

  • react/jsx-child-element-spacing
  • react/jsx-closing-bracket-location
  • react/jsx-closing-tag-location
  • react/jsx-curly-brace-presence
  • react/jsx-curly-newline
  • react/jsx-curly-spacing
  • react/jsx-equals-spacing
  • react/jsx-first-prop-new-line
  • react/jsx-indent-props
  • react/jsx-indent
  • react/jsx-max-props-per-line
  • react/jsx-newline
  • react/jsx-one-expression-per-line
  • react/jsx-pascal-case
  • react/jsx-props-no-multi-spaces
  • react/jsx-sort-default-props
  • react/jsx-sort-props
  • react/jsx-space-before-closing
  • react/jsx-tag-spacing
  • react/jsx-wrap-multilines

Outdated or obsolete rules

These rules are considered outdated or obsolete. They are not going to be supported by this plugin.

  • react/default-props-match-prop-types
  • react/forbid-foreign-prop-types
  • react/forbid-prop-types
  • react/no-unused-prop-types
  • react/prefer-exact-props
  • react/prefer-es6-class
  • react/prefer-stateless-function
  • react/require-default-props
  • react/require-optimization
  • react/sort-default-props
  • react/sort-prop-types
  • react/state-in-constructor
  • react/static-property-placement
  • react/jsx-no-bind

Work in progress rules

JSX rules

  • jsx/max-depth

Naming convention rules

  • naming-convention/boolean-prop
  • naming-convention/handler-prop

React rules

  • react/prefer-readonly-props
  • react/ban-component-props
  • react/ban-components
  • #294
  • react/no-unused-class-component-members
  • react/no-unsorted-class-component-members

Rule Request: `ensure-custom-hooks-using-other-hooks`

Valid

const useData = (key) => {
  // Valid, because useData is using other React Hooks.
  return useSWR(key);
}

Invalid

const useClassnames = (obj) => {
  // Invalid, because useClassnames doesn't use any other React Hooks.
  var k, cls='';
  for (k in obj) {
    if (obj[k]) {
      cls && (cls += ' ');
      cls += k;
    }
  }
  return cls;
}

Fail to install `@eslint-react/eslint-plugin`

❯ ni @eslint-react/eslint-plugin
 ERR_PNPM_FETCH_404  GET https://registry.npmjs.org/@eslint-react%2Feslint-plugin-hooks: Not Found - 404

This error happened while installing the dependencies of @eslint-react/[email protected]

@eslint-react/eslint-plugin-hooks is not in the npm registry, or you have no permission to fetch it.

An authorization header was used: Bearer npm_[hidden]
Progress: resolved 420, reused 397, downloaded 0, added 0

The declared dependency @eslint-react/eslint-plugin-xxx is not published to npm, we have packaged it into @eslint-react/eslint-plugin.

TypeError: Key "rules": Key "@eslint-react/jsx/no-array-index-key": Could not find plugin "@eslint-react/jsx".

Will you release different packages for different rules or modify the default preset? For example, jsx/no-array-index-key corresponds to @eslint-react/jsx.

Currently, it is not possible to use the @eslint-react/eslint-plugin package to lint as described in the readme, because jsx-related rules cannot be correctly mapped.

TypeError: Key "rules": Key "@eslint-react/jsx/no-array-index-key": Could not find plugin "@eslint-react/jsx".

I'm using eslint flat config.

[bug] `no-missing-component-display-name` can not check `displayName` from `MemberExpression`

Describe the bug

This should not report an error

const someThing = {
  displayName: "someThing",
}
const Component = React.forwardRef(() => <div/>)
Component.displayName = someThing.displayName

Maybe add a check in componentCollector

const maybeRightValue = match(right)
    .with({ type: NodeType.Literal }, ({ value }) => O.some(value))
    .with({ type: NodeType.TemplateLiteral }, n => O.some(getStaticValue(n)?.value))
    .with({ type: NodeType.MemberExpression }, n => {
	// here
    })
    .with({ type: NodeType.Identifier }, n => {
      return F.pipe(
        findVariableByNameUpToGlobal(n.name, context.getScope()),
        O.flatMap(getVariableInit(0)),
        O.filter(isOneOf([NodeType.Literal, NodeType.TemplateLiteral])),
        O.map(getStaticValue),
        O.flatMapNullable(v => v?.value),
      );
    })
    .otherwise(O.none);

Reproduction

No response

Expected behavior

No response

Platform and versions

node: v18.18.2
@eslint-react: v0.8.10-beta.2

Stack trace

No response

Additional context

No response

Can not work with `eslint-define-config`

import { Pretty } from '@eslint-react/tools';
import * as debug from '@eslint-react/eslint-plugin-debug';
import * as hooks from '@eslint-react/eslint-plugin-hooks';
import * as jsx from '@eslint-react/eslint-plugin-jsx';
import * as namingConvention from '@eslint-react/eslint-plugin-naming-convention';
import * as react from '@eslint-react/eslint-plugin-react';
import { ESLintUtils } from '@typescript-eslint/utils';

type Rules = typeof _default.rules;
type RulesWithOptions = Pretty<
  {
    [ruleName in keyof Rules as `@eslint-react/${ruleName}`]: Parameters<Rules[ruleName]["create"]>[0]["options"];
  }
>;

declare module "eslint-define-config" {
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
  export interface CustomRuleOptions extends RulesWithOptions {}
}

In user-side code, the type for unpublished @eslint-react/tools cannot be found.
We may need something like tsup --dts-resolve, or not use types from internal packages.

Transfer project back to personal GitHub

image

It looks like we're going to run out of free Netlify credit in just a few days, and I need to transfer the project back to a personal GitHub so we can use Vercel without having to buy a paid team plan, and a lot of other services require a paid plan for projects under the organization, which I don't have the money to pay for at the moment.

[bug] `Error: Key "rules": Key "@eslint-react/naming-convention/filename-extension": Value "as-needed" should be object.`

Describe the bug

Per documentation (https://eslint-react.rel1cx.io/rules/naming-convention-filename-extension)

This rule has a string option

Reproduction

'@eslint-react/naming-convention/filename-extension': ['error', 'as-needed']

Expected behavior

No response

Platform and versions

Node.js 20.7.0
@eslint-react 0.9.5

Stack trace

No response

Additional context

The documentation is outdated and should be updated.

`no-leaked-conditional-rendering` maybe no need to check conditional expression

{ x ? y : z }
{ y }
{ x && y }

I just realized that maybe y in a normal expression is no different from y in a conditional expression. They are both what the user expects to be rendered. But x is different, when x is false, it may cause rendering of something other than what is expected.

For example, the following should be the correct code

const SomeComponent = () => <div />;
const someFunction = (input: unknown) => input as number;

const App = ({ someCondition }: { someCondition?: number | undefined }) => {
  return <>{someCondition ? someFunction(someCondition) : <SomeComponent />}</>;
};

Rule Request: implement `eslint-plugin-react` rules


  • Add all rules implementation to rules exports
  • Link all rules implementation documentation to README.md

  • jsx/no-script-url: Custom Component and prop support

[Rule Request] `react-hooks/ensure-use-callback-has-non-empty-deps`

Describe the problem

Describe the problem

const Comp = () => {
  const style = useCallback((theme: MantineTheme) => ({
    input: {
      fontFamily: theme.fontFamilyMonospace
    }
  }), []);
  return <Button sx={style} />
}

The useCallback here is completely not necessary, it can be hoisted:

const style = (theme: MantineTheme) => ({
  input: {
    fontFamily: theme.fontFamilyMonospace
  }
});

const Comp = () => {
  return <Button sx={style} />
}

Describe the solution you'd like

Find all useCallback hook inside components, and check if their dependency array has 0 elements.

Alternatives considered

No response

Additional context

No response

[feat] Request rule: `require-use-memo-use-callback-to-have-non-empty-dependency-array`

Describe the problem

const Comp = () => {
  const style = useCallback((theme: MantineTheme) => ({
    input: {
      fontFamily: theme.fontFamilyMonospace
    }
  }), []);
  return <Button sx={style} />
}

The useCallback here is completely not necessary, it can be hoisted:

const style = (theme: MantineTheme) => ({
  input: {
    fontFamily: theme.fontFamilyMonospace
  }
});

const Comp = () => {
  return <Button sx={style} />
}

Describe the solution you'd like

Find all useCallback and useMemo hook inside components, and check if their dependency array has 0 elements.

Alternatives considered

No response

Additional context

No response

A more agnosticism plugin name `eslint-plugin-jsx`?

Hi @Rel1cx .

I believe jsx is not only for react and this amazing ESLint plugin can benefit other jsx friendly frameworks like preact, solid, vue, etc.

And I just got the eslint-plugin-jsx npm package maintainer permission from @jkroso , I'd like to propose to change the current plugin more agnosticism.

How do you think?

Don't mind if you don't agree with me.

Best wishes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.