Skip to content

Commit

Permalink
[eslint-plugin-react-hooks] update naming rules to disallow _component
Browse files Browse the repository at this point in the history
  • Loading branch information
kassens committed Aug 31, 2022
1 parent eaba42e commit 203a6a2
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 21 deletions.
7 changes: 7 additions & 0 deletions packages/eslint-plugin-react-hooks/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Next Release

* **New Violations:** Components now need to be named with a capital letter, potentially prefixed with an underscore. E.g. `Button` or `_Button`. `_component` is no longer valid. ([@kassens](https://github.com/kassens)) in [#TBD](https://github.com/facebook/react/pull/TBD)
* Hooks can now have an optional underscore prefix, e.g. `_useName`. ([@kassens](https://github.com/kassens)) in [#TBD](https://github.com/facebook/react/pull/TBD)

## 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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,10 @@ const tests = {
})
`,
`
// Valid because they're not matching use[A-Z].
// Valid because they're not matching ^_*use[A-Z].
fooState();
use();
_use();
_useState();
use_hook();
// also valid because it's not matching the PascalCase namespace
jest.useFakeTimer()
Expand Down Expand Up @@ -406,17 +405,6 @@ const tests = {
const [myState, setMyState] = useState(null);
}
`,
`
// Valid, but should be invalid. '_useHook' is currently recognized as a component.
function Component(props) {
if (cond) {
_useHook();
}
}
function _useHook() {
useState(null);
}
`,
],
invalid: [
{
Expand All @@ -443,6 +431,7 @@ const tests = {
`,
errors: [
topLevelError('Hook.useState'),
topLevelError('Hook._useState'),
topLevelError('Hook.use42'),
topLevelError('Hook.useHook'),
],
Expand Down Expand Up @@ -652,6 +641,20 @@ const tests = {
functionError('useHookInsideNormalFunction', 'normalFunctionWithHook'),
],
},
{
code: `
// These are neither functions nor hooks.
function _normalFunctionWithHook() {
useHookInsideNormalFunction();
}
function _useNotAHook() {
useHookInsideNormalFunction();
}
`,
errors: [
functionError('useHookInsideNormalFunction', '_normalFunctionWithHook'),
],
},
{
code: `
// Invalid because it's dangerous and might not warn otherwise.
Expand Down Expand Up @@ -893,17 +896,33 @@ const tests = {
// they are confusing anyway due to the use*() convention
// already being associated with Hooks.
useState();
_useState();
if (foo) {
const foo = React.useCallback(() => {});
}
useCustomHook();
`,
errors: [
topLevelError('useState'),
topLevelError('_useState'),
topLevelError('React.useCallback'),
topLevelError('useCustomHook'),
],
},
{
code: `
// Valid, but should be invalid. '_useHook' is currently recognized as a component.
function Component(props) {
if (cond) {
_useHook();
}
}
function _useHook() {
useState(null);
}
`,
errors: [conditionalError('_useHook')],
},
{
code: `
// Technically this is a false positive.
Expand Down
13 changes: 5 additions & 8 deletions packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

function isHookName(s) {
return /^use[A-Z0-9].*$/.test(s);
return /^_*use[A-Z0-9]/.test(s);
}

/**
Expand All @@ -42,16 +42,13 @@ 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, potentially prefixed with `_`.
* So `MyComponent` or `_MyComponent` are valid component names for instance.
* `_myComponent` is not a valid component name.
*/

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) {
Expand Down

0 comments on commit 203a6a2

Please sign in to comment.