Adds illegal anonymous function error msg
The only legal scenario for a React component function to be anonymous i.e. unnamed, is when it is passed as a callback to either React.forwardRef or React.memo.
This can be verified on eslint's RulesOfHooks. It uses a different eliminatory logic to rule out violations than this project, so we won't have a 1:1 match in terms of rule verification. But essentially, if a hook's ancestor (AST) node —the function declaration statement— is not in a forwardRef or memo call AND has no valid identifier (conditional stated here), than it falls back to this branch.
Current behavior would treat this error as "A hook hook cannot be used inside of another function", which is misleading.
Resolves #29.
Hey, thanks for the thorough review!
As for the changes of this PR, I believe that ensuring that the ancestor's parent node is not a hook or a component clears out the scenarios you mentioned that were being misclassified. I can't think of any more of them, but I appreciate if you can exhaust this further.
After reviewing your comments, I realized that you are correct: the walker is missing being aware of the broader tree path it is in, and whether it is inside a nested valid component or hook. Which seems to be another issue altogether.
Consider the following statement:
const a = forwardRef(() => {
while(true) {
return React.memo(() => {
const x = useRef();
})
}
})
~It is an invalid usage of hooks but it doesn't trigger any rules, because current rules rely only on, at most, two levels above ancestor.parent in order to trigger some rules~.
Edit: it is a valid snippet for this tslint rule.
Thanks for introducing more updates :+1:
It is an invalid usage of hooks but it doesn't trigger any rules, because current rules rely only on, at most, two levels above ancestor.parent in order to trigger some rules.
In terms of this rule, it does not seem that invalid to me. In the snippet you shared, useRef is called within React.memo, which is a valid context for a hook call. The fact that we're returning a component type instead of a component instance from forwardRef is beyond the responsibility of this rule (and a linter in general, IMO). If you asked me, this is the type of error that should be caught by TypeScript because it's a type error and not strictly related to hooks.
In the snippet you shared, useRef is called within React.memo, which is a valid context for a hook call.
That is correct. I was attempting to exercise corner cases that relied on a broader context awareness, but it's not the case for this particular linter —which relies mostly on the enclosing scope in which the hook is defined. Appreciate your patience on clearing those out 👍
Please let me know if you think there's anything left prior to sign off.