如何编写ESLint规则完全禁止在useEffect清理函数中使用Hello关键字
问题分析
你当前的规则无法拦截多层链式调用的核心原因有两个:
- 只判断了
CallExpression的第一层callee.object是否为Hello,没有处理多层MemberExpression嵌套的场景(比如Hello.someObject.a是多层成员访问,最内层的object才是Hello) - 匹配到
Hello时的返回值写反了,Array.find需要返回true才会捕获对应节点,你原来的逻辑匹配到后返回false,会漏掉命中的节点
修复方案
新增一个递归工具函数,用来判断任意表达式节点的最左侧根标识符是否为Hello,不管嵌套多少层成员访问都能识别。再调整遍历逻辑,覆盖清理函数内所有可能出现Hello的场景。
修改后的完整规则代码
export default function (context) { const filename = context.getFilename(); if (filename.includes(".test.ts")) return {}; // 新增工具函数:递归判断节点的根标识符是否为Hello const hasRootHello = (node) => { if (!node) return false; // 是标识符直接判断名称 if (node.type === 'Identifier') return node.name === 'Hello'; // 是成员表达式则递归判断左侧的object节点 if (node.type === 'MemberExpression') return hasRootHello(node.object); // 是调用表达式则递归判断callee节点 if (node.type === 'CallExpression') return hasRootHello(node.callee); return false; }; return { Identifier: (node) => { if (node.name !== "useEffect" || node.parent.type !== "CallExpression") return; const useEffectCallback = node.parent.arguments[0]; if (useEffectCallback.type !== "ArrowFunctionExpression" && useEffectCallback.type !== "FunctionExpression") return; const callbackBody = useEffectCallback.body; if (callbackBody.type !== "BlockStatement") return; // 找到useEffect回调里返回的清理函数 const returnStatement = callbackBody.body.find(stmt => stmt.type === "ReturnStatement"); if (!returnStatement?.argument) return; const cleanupFn = returnStatement.argument; if (cleanupFn.type !== "ArrowFunctionExpression" && cleanupFn.type !== "FunctionExpression") return; const cleanupBody = cleanupFn.body; if (cleanupBody.type !== "BlockStatement") return; // 遍历清理函数内所有语句,命中Hello直接上报 for (const stmt of cleanupBody.body) { if (stmt.type !== 'ExpressionStatement') continue; if (hasRootHello(stmt.expression)) { context.report({ node: stmt, message: "ERROR, do not use `Hello` in cleanup function", }); } } } }; }
覆盖场景说明
修改后的规则可以拦截所有useEffect清理函数中使用Hello的场景:
- 直接使用
Hello标识符 - 单层调用
Hello.alert() - 任意多层链式调用
Hello.a.b.c()、Hello.someObj.func() - 其他所有以Hello为根标识符的表达式调用
内容的提问来源于stack exchange,提问作者June Lee
相关产品推荐
相关产品推荐

