jsx-eslint / eslint-plugin-react

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

[feature request] no-undef for undefined class component methods #3012

Closed alfredoreduarte closed 2 years ago

alfredoreduarte commented 3 years ago

Something that detects undefined class methods would be useful. Currently, this passes undetected:

class MyComponent extends React.Component {
    onTap = () => {
        this.undefinedMethod()
    }
    render = () => {
        return <Button onTap={this.onTap}>
    }
}

My setup:

{
  "name": "~",
  "main": "index.js",
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "web": "expo start --web",
    "start": "react-native start",
    "prettier-watch": "onchange '**/*.js' -- prettier --write {{changed}}",
    "eslint-watch": "onchange '**/*.js' -- eslint {{changed}}"
  },
  "dependencies": {
    "@react-native-async-storage/async-storage": "^1.15.5",
    "@react-navigation/bottom-tabs": "^5.11.11",
    "@react-navigation/drawer": "^5.12.5",
    "@react-navigation/native": "^5.9.4",
    "@react-navigation/stack": "^5.14.5",
    "@sentry/react-native": "^2.4.3",
    "axios": "^0.21.1",
    "dateformat": "^4.5.1",
    "expo": "~41.0.1",
    "expo-ads-admob": "~10.0.4",
    "expo-ads-facebook": "~10.0.4",
    "expo-firebase-analytics": "~4.0.2",
    "expo-in-app-purchases": "^10.1.1",
    "expo-linear-gradient": "~9.1.0",
    "expo-linking": "^2.2.3",
    "expo-localization": "~10.1.0",
    "expo-network": "~3.1.1",
    "expo-notifications": "~0.11.6",
    "expo-splash-screen": "~0.10.2",
    "expo-sqlite": "~9.1.0",
    "expo-status-bar": "~1.0.4",
    "expo-store-review": "~4.0.2",
    "expo-updates": "~0.5.4",
    "hashids": "^2.2.8",
    "i18n-js": "^3.8.0",
    "moment": "^2.29.1",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "~0.63.4",
    "react-native-appearance": "^0.3.4",
    "react-native-branch": "^5.0.0",
    "react-native-elements": "^3.4.1",
    "react-native-fbsdk-next": "^4.3.0",
    "react-native-gesture-handler": "~1.10.2",
    "react-native-get-random-values": "^1.7.0",
    "react-native-inappbrowser-reborn": "^3.5.1",
    "react-native-navigation-bar-color": "^2.0.1",
    "react-native-reanimated": "~2.1.0",
    "react-native-render-html": "^5.1.0",
    "react-native-responsive-fontsize": "^0.5.0",
    "react-native-responsive-screen": "^1.4.2",
    "react-native-safe-area-context": "^3.2.0",
    "react-native-screens": "~3.0.0",
    "react-native-svg": "^12.1.1",
    "react-native-unimodules": "~0.13.3",
    "react-native-web": "~0.13.12",
    "react-native-webview": "^11.6.2",
    "react-redux": "^7.2.4",
    "redux-persist": "^6.0.0",
    "redux-thunk": "^2.3.0",
    "rn-placeholder": "^3.0.3",
    "sentry-expo": "^3.1.0",
    "uuid": "^8.3.2"
  },
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "~25.2.6",
    "eslint": "^7.29.0",
    "eslint-plugin-react": "^7.24.0",
    "eslint-plugin-react-native": "^3.11.0",
    "jest": "~25.2.6",
    "onchange": "^6.1.0",
    "react-test-renderer": "~16.13.1"
  },
  "private": true
}
{
    "env": {
        "browser": true,
        "es2021": true,
        "react-native/react-native": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended"
    ],
    "parser": "babel-eslint",
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "react-native"
    ],
    "settings": {
        "react": {
            "version": "detect"
        }
    },
    "rules": {
        "no-undef": 2,
        "no-unused-vars": 2,
        "no-unsafe-finally": 2,
        "react/no-unescaped-entities": 2,
        "react/prop-types": "off",
        "react/jsx-no-undef": "error",
        "react/no-this-in-sfc": 2,
        "react/no-unused-state": 2,
        "react/no-direct-mutation-state": "error",
        "react-native/split-platform-components": 2,
        "react-native/split-platform-components": 2,
        "react-native/no-single-element-style-arrays": 2,
        "react-native/no-raw-text": 2
    }
}
ljharb commented 3 years ago

There's so many ways undefinedMethod could exist - this wouldn't be a reliable rule, and not really a useful one.

If you're still writing a class component, you should be unit-testing it, and using code coverage to show you that that code is unused.