Skip to content

Commit 1299697

Browse files
committed
[eslint-plugin-react-hooks] update naming rules to disallow _component
1 parent eaba42e commit 1299697

File tree

3 files changed

+44
-21
lines changed

3 files changed

+44
-21
lines changed

packages/eslint-plugin-react-hooks/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## Next Release
2+
3+
* **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 [#25162](https://github.com/facebook/react/pull/25162)
4+
* Hooks can now have an optional underscore prefix, e.g. `_useName`. ([@kassens](https://github.com/kassens)) in [#25162](https://github.com/facebook/react/pull/25162)
5+
6+
## 4.6.0
7+
18
## 4.5.0
29

310
* Fix false positive error with large number of branches. ([@scyron6](https://github.com/scyron6) in [#24287](https://github.com/facebook/react/pull/24287))

packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,10 @@ const tests = {
200200
})
201201
`,
202202
`
203-
// Valid because they're not matching use[A-Z].
203+
// Valid because they're not matching ^_*use[A-Z].
204204
fooState();
205205
use();
206206
_use();
207-
_useState();
208207
use_hook();
209208
// also valid because it's not matching the PascalCase namespace
210209
jest.useFakeTimer()
@@ -406,17 +405,6 @@ const tests = {
406405
const [myState, setMyState] = useState(null);
407406
}
408407
`,
409-
`
410-
// Valid, but should be invalid. '_useHook' is currently recognized as a component.
411-
function Component(props) {
412-
if (cond) {
413-
_useHook();
414-
}
415-
}
416-
function _useHook() {
417-
useState(null);
418-
}
419-
`,
420408
],
421409
invalid: [
422410
{
@@ -443,6 +431,7 @@ const tests = {
443431
`,
444432
errors: [
445433
topLevelError('Hook.useState'),
434+
topLevelError('Hook._useState'),
446435
topLevelError('Hook.use42'),
447436
topLevelError('Hook.useHook'),
448437
],
@@ -652,6 +641,20 @@ const tests = {
652641
functionError('useHookInsideNormalFunction', 'normalFunctionWithHook'),
653642
],
654643
},
644+
{
645+
code: `
646+
// These are neither functions nor hooks.
647+
function _normalFunctionWithHook() {
648+
useHookInsideNormalFunction();
649+
}
650+
function _useNotAHook() {
651+
useHookInsideNormalFunction();
652+
}
653+
`,
654+
errors: [
655+
functionError('useHookInsideNormalFunction', '_normalFunctionWithHook'),
656+
],
657+
},
655658
{
656659
code: `
657660
// Invalid because it's dangerous and might not warn otherwise.
@@ -893,17 +896,33 @@ const tests = {
893896
// they are confusing anyway due to the use*() convention
894897
// already being associated with Hooks.
895898
useState();
899+
_useState();
896900
if (foo) {
897901
const foo = React.useCallback(() => {});
898902
}
899903
useCustomHook();
900904
`,
901905
errors: [
902906
topLevelError('useState'),
907+
topLevelError('_useState'),
903908
topLevelError('React.useCallback'),
904909
topLevelError('useCustomHook'),
905910
],
906911
},
912+
{
913+
code: `
914+
// Valid, but should be invalid. '_useHook' is currently recognized as a component.
915+
function Component(props) {
916+
if (cond) {
917+
_useHook();
918+
}
919+
}
920+
function _useHook() {
921+
useState(null);
922+
}
923+
`,
924+
errors: [conditionalError('_useHook')],
925+
},
907926
{
908927
code: `
909928
// Technically this is a false positive.

packages/eslint-plugin-react-hooks/src/RulesOfHooks.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

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

2222
/**
@@ -42,16 +42,13 @@ function isHook(node) {
4242

4343
/**
4444
* Checks if the node is a React component name. React component names must
45-
* always start with a non-lowercase letter. So `MyComponent` or `_MyComponent`
46-
* are valid component names for instance.
45+
* always start with an uppercase letter, potentially prefixed with `_`.
46+
* So `MyComponent` or `_MyComponent` are valid component names for instance.
47+
* `_myComponent` is not a valid component name.
4748
*/
4849

4950
function isComponentName(node) {
50-
if (node.type === 'Identifier') {
51-
return !/^[a-z]/.test(node.name);
52-
} else {
53-
return false;
54-
}
51+
return node.type === 'Identifier' && /^_*[A-Z]/.test(node.name);
5552
}
5653

5754
function isReactFunction(node, functionName) {

0 commit comments

Comments
 (0)