mirror of
https://github.com/danbulant/oxc
synced 2026-05-22 05:38:54 +00:00
fix(linter): rules-of-hooks fix false positive with default export (#7570)
closes #7555
This commit is contained in:
parent
cb1f8e6e03
commit
4e3044e225
2 changed files with 25 additions and 32 deletions
|
|
@ -172,13 +172,12 @@ impl Rule for RulesOfHooks {
|
||||||
}) => {
|
}) => {
|
||||||
let ident = get_declaration_identifier(nodes, parent_func.id());
|
let ident = get_declaration_identifier(nodes, parent_func.id());
|
||||||
|
|
||||||
// Hooks cannot be called inside of export default functions or used in a function
|
// Hooks cannot be used in a function declaration outside of a react component or hook.
|
||||||
// declaration outside of a react component or hook.
|
|
||||||
// For example these are invalid:
|
// For example these are invalid:
|
||||||
// const notAComponent = () => {
|
// const notAComponent = () => {
|
||||||
// return () => {
|
// return () => {
|
||||||
// useState();
|
// useState();
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// --------------
|
// --------------
|
||||||
// export default () => {
|
// export default () => {
|
||||||
|
|
@ -192,9 +191,7 @@ impl Rule for RulesOfHooks {
|
||||||
// useState(0);
|
// useState(0);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
if ident.is_some_and(|name| !is_react_component_or_hook_name(&name))
|
if ident.is_some_and(|name| !is_react_component_or_hook_name(&name)) {
|
||||||
|| is_export_default(nodes, parent_func.id())
|
|
||||||
{
|
|
||||||
return ctx.diagnostic(diagnostics::function_error(
|
return ctx.diagnostic(diagnostics::function_error(
|
||||||
*span,
|
*span,
|
||||||
hook_name,
|
hook_name,
|
||||||
|
|
@ -400,14 +397,6 @@ fn get_declaration_identifier<'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_export_default<'a>(nodes: &'a AstNodes<'a>, node_id: NodeId) -> bool {
|
|
||||||
nodes
|
|
||||||
.ancestor_ids(node_id)
|
|
||||||
.map(|id| nodes.get_node(id))
|
|
||||||
.nth(1)
|
|
||||||
.is_some_and(|node| matches!(node.kind(), AstKind::ExportDefaultDeclaration(_)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// `node_id` should always point to a valid `Function`.
|
/// `node_id` should always point to a valid `Function`.
|
||||||
fn is_memo_or_forward_ref_callback(nodes: &AstNodes, node_id: NodeId) -> bool {
|
fn is_memo_or_forward_ref_callback(nodes: &AstNodes, node_id: NodeId) -> bool {
|
||||||
|
|
@ -916,6 +905,16 @@ fn test() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
",
|
",
|
||||||
|
"export default function App() {
|
||||||
|
const [state, setState] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('Effect called');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <div>{state}</div>;
|
||||||
|
}
|
||||||
|
"
|
||||||
];
|
];
|
||||||
|
|
||||||
let fail = vec![
|
let fail = vec![
|
||||||
|
|
|
||||||
|
|
@ -668,24 +668,18 @@ source: crates/oxc_linter/src/tester.rs
|
||||||
5 │
|
5 │
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
⚠ eslint-plugin-react-hooks(rules-of-hooks): React Hook "useState" is called in function "Anonymous" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".
|
⚠ eslint-plugin-react-hooks(rules-of-hooks): React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
|
||||||
╭─[rules_of_hooks.tsx:2:28]
|
╭─[rules_of_hooks.tsx:4:21]
|
||||||
1 │
|
3 │ if (isVal) {
|
||||||
2 │ ╭─▶ export default () => {
|
4 │ useState(0);
|
||||||
3 │ │ if (isVal) {
|
· ───────────
|
||||||
4 │ │ useState(0);
|
5 │ }
|
||||||
5 │ │ }
|
|
||||||
6 │ ╰─▶ }
|
|
||||||
7 │
|
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
⚠ eslint-plugin-react-hooks(rules-of-hooks): React Hook "useState" is called in function "Anonymous" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".
|
⚠ eslint-plugin-react-hooks(rules-of-hooks): React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
|
||||||
╭─[rules_of_hooks.tsx:2:28]
|
╭─[rules_of_hooks.tsx:4:21]
|
||||||
1 │
|
3 │ if (isVal) {
|
||||||
2 │ ╭─▶ export default function() {
|
4 │ useState(0);
|
||||||
3 │ │ if (isVal) {
|
· ───────────
|
||||||
4 │ │ useState(0);
|
5 │ }
|
||||||
5 │ │ }
|
|
||||||
6 │ ╰─▶ }
|
|
||||||
7 │
|
|
||||||
╰────
|
╰────
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue