react hooks过多,你可能需要这个eslint插件

板凳快报4月中聊到了react组件中hooks的使用泛滥问题,当hooks使用过多会有如下的问题:

  • 代码阅读性差,逻辑分散
  • 性能差 过多的hooks更新会导致页面多次渲染,
  • hooks之间的依赖耦合增加 本身hooks的依赖就已经很难治理,hooks之间的依赖更加不可控。

在思考这个怎么解决这个问题的时候,希望可以通过规则限制的解法来解,因为只有可定义的规则才能在长期的代码维护中一直比较好的运行,在规则与人工review的结合下就能比较好的实现代码的长期治理。本文内容主要基于此,介绍eslint插件的开发过程和react hooks数量限制插件的使用

开发eslint插件

生成插件项目

eslint提供了生成插件的工具generator-eslint

less 复制代码
// 安装全局依赖
npm i -g yo
npm i -g generator-eslint

// 进入到插件目录,生成插件模版
cd testPlugin
yo eslint:plugin
创建文件

开发调试

在创建的文件夹中,在rules中增加自定义的规则。在这里我们要限制hooks的数据,添加了no-too-many-hooks.js,内容如下:

javascript 复制代码
"use strict";
module.exports = {
    meta: {
        docs: {
            // 规则描述
            description: "no too many hooks",
            category: "",
            recommended: false
        },
        fixable: null,  // or "code" or "whitespace"
        // 规则的参数配置 这里设置了两个参数 list代表要关注的hooks列表,numLimit代表限制的数目
        schema: [
            {
                type: "object",
                properties: {
                list: {
                    type: "array",
                },
                numLimit: {
                    type: "number"
                }
                },
                additionalProperties: false,
            },
        ],
        // 报错信息描述
        messages: {
            hooksLimit: "too many hooks you called",
        },
    },

    create: function(context) {
        // 累积的hooks数目
        let currentNum = 0
        return {
            // 解析ast的节点 可以通过[astexplorer](https://astexplorer.net/)来查看对应的节点
            'CallExpression Identifier': (node) => {
                // 获取当前的配置
                const options = context.options[0] || {}
                const list = options.list || ['useState']
                const numLimit = options.numLimit || 5
                // 命中 当前是hook调用
                if (list.includes(node.name)) {
                    // 累积数自增
                    currentNum++
                    // 当前的累积数大于等于配置的数据 报错 匹配到too many hooks you called
                    if(currentNum >= numLimit) {
                        context.report({
                            node,
                            messageId: 'hooksLimit'
                        });
                    }
                    
                }
            },
        };
    }
};

在入口文件中导出规则

javascript 复制代码
"use strict";
module.exports = {
    rules: {
        // 规则名字
        'no-too-many-hooks': require('./rules/no-too-many-hooks'),
    },
    configs: {
        // 定义推荐用法 在使用的时候可以通过recommended或者自己添加当前rule的规则来设定
        recommended: {
            rules: {
                'hooks-limit/no-too-many-hooks': [1, { list: ["useEffect", "useState", "useCallback"], numLimit: 5 }], // 可以省略 eslint-plugin 前缀
            },
        },
    },
};

在开发过程中,需要不断调试当前代码是否生效,可以通过npm link的方式,在插件的目录执行

bash 复制代码
npm link  

在需要使用插件的目录执行

scss 复制代码
npm link eslint-plugin-hooks-limit(定义的插件名字)

eslint-plugin-hooks-limit

安装插件

json 复制代码
// 安装eslit
npm i eslint --save-dev
// 安装插件
npm install eslint-plugin-hooks-limit --save-dev

// 在项目的eslint配置中加入配置 这里设置2个hooks的调用触发eslint的waring
{
    "extends": [
        "next/core-web-vitals",
        "plugin:eslint-plugin-hooks-limit/recommended"
    ],
    "plugins": [
        "hooks-limit"
    ],
    "rules": {
        "hooks-limit/no-too-many-hooks": [2, { "list": ["useEffect", "useState"], "numLimit": 2 } ] // 可以省略 eslint-plugin 前缀
    }
} 

假设react组件中有这样一段代码:

scss 复制代码
 useEffect(() => {
    console.time();
}, [])
useEffect(() => {
    console.time();
}, [])

这个时候运行项目的lint脚本


ps: lint插件写的比较简单,大家可以自己根据代码自己修改使用

欢迎大家关注我的公众号-前端小板凳 一起学习进步!

相关推荐
AlienZHOU13 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc16 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师17 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen18 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒18 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow18 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林81818 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang8007818 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明18 小时前
第 6 章 组件进阶
前端·vue.js
江华森18 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端