パッケージの詳細

eslint-plugin-react-prefer-function-component

tatethurston345.7kMIT4.0.1

ESLint plugin that prevents the use of JSX class components

eslint react no class, eslint react class, lint react no class, lint react class

readme

eslint-plugin-react-prefer-function-component

An ESLint plugin that prevents the use of React class components.


What is this? 🧐

An ESLint plugin that prevents the use of React class components. While this plugin specifically calls out React, it will work with Preact, Inferno, or other JSX libraries.

Motivation

Since the addition of hooks, it has been possible to write stateful React components using only functions.

Leaving the choice between class or function components up to the community is great, but generally within a codebase I want consistency: either we're writing class components and HoCs or we're using function components and hooks. Straddling the two adds unnecessary hurdles for sharing reusable logic.

By default, class components that use componentDidCatch are enabled because there is currently no hook alternative for React. This option is configurable via allowComponentDidCatch.

This rule is intended to complement the eslint-plugin-react rule set.

FAQ

What about ErrorBoundary class components? Does this lint rule support those?

Yes it does. Error Boundaries are implemented by defining componentDidCatch. Because there is currently no hook equivalent, class components that implement componentDidCatch are allowed by default.

This option is configurable.

What about eslint-plugin-react/prefer-stateless-function?

eslint-plugin-react/prefer-stateless-function allows class components that implement any methods or properties other than render. This rule is stricter and prevents the use of any class components. This open issue explains the limitations of prefer-stateless-function and the motivations for this plugin.

Why didn't you contribute this rule to https://github.com/yannickcr/eslint-plugin-react?

I'm discussing this in an open issue and pull request on eslint-plugin-react. At this time, the maintainer of eslint-plugin-react is unconvinced that function component enforcement should be a lint rule. If you would like to see this rule added to eslint-plugin-react, please join the discussion on the issue or pull request.

Installation & Usage 📦

  1. Install:
$ npm install eslint eslint-plugin-react-prefer-function-component --save-dev
  1. Update your eslint.config.js:
import eslint from "@eslint/js";
import reactRecommended from "eslint-plugin-react/configs/recommended.js";
import preferFunctionComponent from "eslint-plugin-react-prefer-function-component/config";

export default [
  { files: ["**/*.{js,jsx}"] },
  eslint.configs.recommended,
  reactRecommended,
  preferFunctionComponent.configs.recommended,
];

ESLint Legacy Configuration

.eslintrc configuration:

module.exports = {
  extends: ["plugin:react-prefer-function-component/recommended"],
};

Or customize:

module.exports = {
  plugins: ["react-prefer-function-component"],
  rules: {
    "react-prefer-function-component/react-prefer-function-component": [
      "error",
      { allowComponentDidCatch: false },
    ],
  },
};

For more configuration examples, take a look at the examples directory.

Rule Details

This rule will flag any React class components that don't use componentDidCatch.

Examples of incorrect code for this rule:

import { Component } from "react";

class Foo extends Component {
  render() {
    return <div>{this.props.foo}</div>;
  }
}

Examples of correct code for this rule:

function Foo(props) {
  return <div>{props.foo}</div>;
}
const Foo = ({ foo }) => <div>{foo}</div>;

Rule Options

...
"react-prefer-function-component": [<enabled>, { "allowComponentDidCatch": <allowComponentDidCatch>, "allowJsxUtilityClass": <allowJsxUtilityClass> }]
...
  • enabled: for enabling the rule. 0=off, 1=warn, 2=error. Defaults to 0.
  • allowComponentDidCatch: optional boolean. set to false if you want to also flag class components that use componentDidCatch (defaults to true).
  • allowJsxUtilityClass: optional boolean. set to true if you want to allow classes that contain JSX but aren't class components (defaults to false).

allowComponentDidCatch

When true (the default) the rule will ignore components that use componentDidCatch

Examples of correct code for this rule:

import { Component } from "react";

class Foo extends Component {
  componentDidCatch(error, errorInfo) {
    logErrorToMyService(error, errorInfo);
  }

  render() {
    return <div>{this.props.foo}</div>;
  }
}

When false the rule will also flag components that use componentDidCatch

Examples of incorrect code for this rule:

import { Component } from "react";

class Foo extends Component {
  componentDidCatch(error, errorInfo) {
    logErrorToMyService(error, errorInfo);
  }

  render() {
    return <div>{this.props.foo}</div>;
  }
}

allowJsxUtilityClass

When true the rule will ignore JS classes that aren't class Components

Examples of correct code for this rule:

import { Bar } from "./Bar";

class Foo {
  getBar() {
    return <Bar />;
  }
}

When false (the default) the rule will flag any class with JSX

Examples of incorrect code for this rule:

import { Bar } from "./Bar";

class Foo {
  getBar() {
    return <Bar />;
  }
}

Contributing 👫

PR's and issues welcomed! For more guidance check out CONTRIBUTING.md

Licensing 📃

See the project's MIT License.

更新履歴

Changelog

v4.0.1

  • Fix flat config issue. See #23. Thanks @MariaSolOs!

v4.0.0

  • Add react- prefix to the flat configuration rule name. When using ESLint's flat configuration, the exported configuration from this package now "react-prefer-function-component". Previously it was "prefer-function-component". Practically speaking, no changes are expected from consumers of this package.

Action would only be necessary if there is an existing plugin in your ESLint configuration using the "react-prefer-function-component" name, or if you're programmatically processing your ESLint configuration and expecting to find "prefer-function-component".

See #20. Thanks @MariaSolOs!

v3.4.0

  • Improved TypeScript type for the configuration object. See #17. Thanks @PrettyCoffee!

v3.3.0

Adds ESLint's new configuration system, flat config. If you're using the new flat config:

`eslint.config.js`:

```js
import eslint from "@eslint/js";
import reactRecommended from "eslint-plugin-react/configs/recommended.js";
import preferFC from "eslint-plugin-react-prefer-function-component/config";

export default [
  { files: ["**/*.{js,jsx}"] },
  eslint.configs.recommended,
  reactRecommended,
  preferFC.configs.recommended,
];
```

v3.2.0

  • The plugin's recommended configuration has been fixed, so plugins can be dropped from your .eslintrc when using the recommended settings:

    module.exports = {
    -  plugins: ["react-prefer-function-component"],
      extends: ["plugin:react-prefer-function-component/recommended"],
    };

    Thanks @alecmev!

v3.1.0

  • New option: allowJsxUtilityClass. This configuration option permits JSX utility classes: classes that have methods that return JSX but are not themselves components(they do not extend from a Component class or have a render method).

    The following is now permitted when enabling this configuration option:

    class Foo {
      getBar() {
        return <Bar />;
      }
    }

    Thanks noahm for the contribution!

v3.0.0

Detects class components that extend the Component class, even if they do not use any JSX. Now errors on manager, business logic, and other renderless class components that extend Component. Previously the below was not caught:

class TimerComponent extends React.Component {
  /// ...

  componentWillMount() {
    this.startTimer();
  }

  componentWillUnmount() {
    this.stopTimer();
  }

  render() {
    null;
  }
}

Thanks @wo1ph for the improvements!

v2.0.0

Support for createClass has been dropped. Usage of createClass will no longer be detected.

Now errors on any JSX usage within a class. Previously the below was not caught:

import Document from "next/document";

class MyDocument extends Document {
  render() {
    <>...</>;
  }
}

v1.0.0

No API changes. This library will now follow semantic versioning.