You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:54:07