Skip to content

Commit

Permalink
Merge pull request #26 from adbutterfield/conditionally-returned-comp…
Browse files Browse the repository at this point in the history
…onent

Detect violations in conditionally returned components
  • Loading branch information
kopiro authored Nov 14, 2023
2 parents 64a0471 + 8aba834 commit a7a4ca4
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
38 changes: 29 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ const isDOMGlobalName = (name) => {
return name in browserGlobals && !(name in nodeGlobals);
};

const isJSXElementOrFragment = (argumentType) => {
return argumentType === "JSXElement" || argumentType === "JSXFragment";
};

const isReturnValueNull = (argument) => {
return argument.type === "Literal" && argument.value === null;
};

const isReturnValueJSXOrNull = (scope) => {
if (
scope.block &&
Expand All @@ -16,15 +24,27 @@ const isReturnValueJSXOrNull = (scope) => {
) {
return (
scope.type === "function" &&
scope.block.body.body.find(
(e) =>
e &&
e.type === "ReturnStatement" &&
e.argument &&
(e.argument.type === "JSXElement" ||
e.argument.type === "JSXFragment" ||
(e.argument.type === "Literal" && e.argument.value === null))
)
scope.block.body.body.find((e) => {
if (!(e && e.type === "ReturnStatement" && e.argument)) {
return false;
}
if (
isJSXElementOrFragment(e.argument.type) ||
isReturnValueNull(e.argument)
) {
return true;
}
if (
e.argument.type === "ConditionalExpression" &&
(isJSXElementOrFragment(e.argument.consequent.type) ||
isReturnValueNull(e.argument.consequent)) &&
(isJSXElementOrFragment(e.argument.alternate.type) ||
isReturnValueNull(e.argument.alternate))
) {
return true;
}
return false;
})
);
}
return false;
Expand Down
10 changes: 10 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ ruleTester.run(pluginName, plugin.rules["no-dom-globals-in-react-fc"], {
}, []);
return <div {...props} ref={ref} />;
})`,
`const Header = () => {
useEffect(() => {
window.addEventListener('resize', () => {});
}, []);
return true ? <div /> : <div />;
}`,
].map((code) => ({ code })),
invalid: [
`const Header = () => {
Expand Down Expand Up @@ -208,6 +214,10 @@ ruleTester.run(pluginName, plugin.rules["no-dom-globals-in-react-fc"], {
const href = url + window.location.hash
return <div {...props} ref={ref}>{href}</div>;
})`,
`const Header = () => {
document.title = "Otto";
return true ? <div /> : <div />;
}`,
].map((code) => ({
code,
errors: [{ message: /Use of DOM global .* FC/ }],
Expand Down

0 comments on commit a7a4ca4

Please sign in to comment.