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插件写的比较简单,大家可以自己根据代码自己修改使用

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

相关推荐
jin12332224 分钟前
基于React Native鸿蒙跨平台地址管理是许多电商、外卖、物流等应用的重要功能模块,实现了地址的添加、编辑、删除和设置默认等功能
javascript·react native·react.js·ecmascript·harmonyos
2501_9209317043 分钟前
React Native鸿蒙跨平台医疗健康类的血压记录,包括收缩压、舒张压、心率、日期、时间、备注和状态
javascript·react native·react.js·ecmascript·harmonyos
落霞的思绪1 小时前
配置React和React-dom为CDN引入
前端·react.js·前端框架
Hacker_Z&Q1 小时前
CSS 笔记2 (属性)
前端·css·笔记
Anastasiozzzz1 小时前
LeetCode Hot100 295. 数据流的中位数 MedianFinder
java·服务器·前端
橙露2 小时前
React Hooks 深度解析:从基础使用到自定义 Hooks 的封装技巧
javascript·react.js·ecmascript
Exquisite.2 小时前
Nginx
服务器·前端·nginx
2501_920931702 小时前
React Native鸿蒙跨平台使用useState管理健康记录和过滤状态,支持多种健康数据类型(血压、体重等)并实现按类型过滤功能
javascript·react native·react.js·ecmascript·harmonyos
打小就很皮...2 小时前
dnd-kit 实现表格拖拽排序
前端·react.js·表格拖拽·dnd-kit
Ulyanov2 小时前
从静态到沉浸:打造惊艳的Web技术发展历程3D时间轴
前端·javascript·html5·gui开发