Add an ESLint rule to prevent the usage of useRef other than for HTML elements. (#2014)
* Add an ESLint rule to prevent the usage of useRef other than for HTML elements Co-authored-by: v1b3m <vibenjamin6@gmail.com> * Bump eslint version and rewrite rule * Fix --------- Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
68
packages/eslint-plugin-twenty/src/rules/no-state-useref.ts
Normal file
68
packages/eslint-plugin-twenty/src/rules/no-state-useref.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { ESLintUtils } from "@typescript-eslint/utils";
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator(() => `https://docs.twenty.com`);
|
||||
|
||||
const noStateUseRef = createRule({
|
||||
create: (context) => {
|
||||
return {
|
||||
CallExpression: (node) => {
|
||||
if (
|
||||
node.callee.type !== "Identifier" ||
|
||||
node.callee.name !== "useRef"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.typeArguments || !node.typeArguments.params?.length) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "noStateUseRef",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const typeParam = node.typeArguments.params[0];
|
||||
|
||||
if (typeParam.type !== "TSTypeReference") {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "noStateUseRef",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeParam.typeName.type !== "Identifier") {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "noStateUseRef",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!typeParam.typeName.name.match(/^(HTML.*Element|Element)$/)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "test",
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
name: "no-state-useref",
|
||||
meta: {
|
||||
docs: {
|
||||
description: "Don't use useRef for state management",
|
||||
},
|
||||
messages: {
|
||||
test: "test",
|
||||
noStateUseRef:
|
||||
"Don't use useRef for state management. See https://docs.twenty.com/developer/frontend/best-practices#do-not-use-useref-to-store-state for more details.",
|
||||
},
|
||||
type: "suggestion",
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
});
|
||||
|
||||
module.exports = noStateUseRef;
|
||||
|
||||
export default noStateUseRef;
|
||||
@ -0,0 +1,51 @@
|
||||
import { RuleTester } from "@typescript-eslint/rule-tester";
|
||||
|
||||
import noStateUseRefRule from "../rules/no-state-useref";
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
project: "./tsconfig.json",
|
||||
tsconfigRootDir: __dirname,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
ruleTester.run("no-state-useref", noStateUseRefRule, {
|
||||
valid: [
|
||||
{
|
||||
code: "const scrollableRef = useRef<HTMLDivElement>(null);",
|
||||
},
|
||||
{
|
||||
code: "const ref = useRef<HTMLInputElement>(null);",
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
code: "const ref = useRef(null);",
|
||||
errors: [
|
||||
{
|
||||
messageId: "noStateUseRef",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "const ref = useRef<Boolean>(null);",
|
||||
errors: [
|
||||
{
|
||||
messageId: "noStateUseRef",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "const ref = useRef<string>('');",
|
||||
errors: [
|
||||
{
|
||||
messageId: "noStateUseRef",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
Reference in New Issue
Block a user