Repository: facebook/react
Pull request: [eslint-plugin-react-hooks] only allow capitalized component names

## Summary

A name like `_useFoo` was previously recognized as a component name ("starting with non-lowercase"). This would misleadingly identify this code as valid (see the first commit in this PR):

```
function Component(props) {
  if (cond) {
    _useHook();
  }
}
function _useHook() {
  useState(null);
}
```

The main change in this PR is that components can no longer start with 1 or more underscores followed by a capital letter. `_component`, `$Component`, `_useFoo` are no longer valid component names.

This means the above code would now be invalid because of the `useState` call in the non-hook/non-component function `_useHook`.

## How did you test this change?

Updated unit tests.

Changed files:
filename: ReactVersions.js
patch: @@ -25,7 +25,7 @@ const ReactVersion = '18.3.0';
 const nextChannelLabel = 'next';
 
 const stablePackages = {
-  'eslint-plugin-react-hooks': '4.7.0',
+  'eslint-plugin-react-hooks': '5.0.0',
   'jest-react': '0.15.0',
   react: ReactVersion,
   'react-art': ReactVersion,

filename: packages/eslint-plugin-react-hooks/CHANGELOG.md
patch: @@ -1,3 +1,9 @@
+## 5.0.0 (next release)
+
+* **New Violations:** Component names now need to start with an uppercase letter instead of a non-lowercase letter. This means `_Button` or `_component` are no longer valid. ([@kassens](https://github.com/kassens)) in [#25162](https://github.com/facebook/react/pull/25162)
+
+## 4.6.0
+
 ## 4.5.0
 
 * Fix false positive error with large number of branches. ([@scyron6](https://github.com/scyron6) in [#24287](https://github.com/facebook/react/pull/24287))

filename: packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
patch: @@ -641,6 +641,21 @@ const tests = {
         functionError('useHookInsideNormalFunction', 'normalFunctionWithHook'),
       ],
     },
+    {
+      code: `
+        // These are neither functions nor hooks.
+        function _normalFunctionWithHook() {
+          useHookInsideNormalFunction();
+        }
+        function _useNotAHook() {
+          useHookInsideNormalFunction();
+        }
+      `,
+      errors: [
+        functionError('useHookInsideNormalFunction', '_normalFunctionWithHook'),
+        functionError('useHookInsideNormalFunction', '_useNotAHook'),
+      ],
+    },
     {
       code: `
         // Invalid because it's dangerous and might not warn otherwise.

filename: packages/eslint-plugin-react-hooks/package.json
patch: @@ -1,7 +1,7 @@
 {
   "name": "eslint-plugin-react-hooks",
   "description": "ESLint rules for React Hooks",
-  "version": "4.6.0",
+  "version": "5.0.0",
   "repository": {
     "type": "git",
     "url": "https://github.com/facebook/react.git",

filename: packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
patch: @@ -16,7 +16,7 @@
  */
 
 function isHookName(s) {
-  return /^use[A-Z0-9].*$/.test(s);
+  return /^use[A-Z0-9]/.test(s);
 }
 
 /**
@@ -42,16 +42,11 @@ function isHook(node) {
 
 /**
  * Checks if the node is a React component name. React component names must
- * always start with a non-lowercase letter. So `MyComponent` or `_MyComponent`
- * are valid component names for instance.
+ * always start with an uppercase letter.
  */
 
 function isComponentName(node) {
-  if (node.type === 'Identifier') {
-    return !/^[a-z]/.test(node.name);
-  } else {
-    return false;
-  }
+  return node.type === 'Identifier' && /^[A-Z]/.test(node.name);
 }
 
 function isReactFunction(node, functionName) {