如何编写难以维护的 React 代码?耦合通用组件与业务逻辑
在众多项目中,React代码的维护经常变得棘手。其中一个常见问题是:将业务逻辑直接嵌入通用组件中,导致通用组件与业务逻辑紧密耦合,使其失去“通用性”。这种做法使通用组件过于依赖具体业务逻辑,导致代码难以维护和扩展。
示例:屎山是如何逐步堆积的
让我们看一个例子:我们在业务组件 PageA 和 PageB 中都使用了通用组件 Card。
function PageA() {
return (
<>
{/* ... */}
{listA.map(({ title, content }) => <Card title={title} content={content} />)}
</>
)
}
function PageB() {
return (
<>
{/* ... */}
{listB.map(({ title, content }) => <Card title={title} content={content} />)}
</>
)
}
function Card({ title, content }) {
return (
<div>
<Title>{title}</Title>
<Content>{content}</Content>
</div>
)
}
某一天,出现了一个新需求:在手机端的所有页面都需要显示 Footer。于是,代码被修改如下:
function PageA({ isMobile }) {
return (
<>
{/* ... */}
{listA.map(({ title, content }) => (
<Card title={title} content={content} isMobile={isMobile} />
))}
</>
)
}
function PageB({ isMobile }) {
return (
<>
{/* ... */}
{listB.map(({ title, content }) => (
<Card title={title} content={content} isMobile={isMobile} />
))}
</>
)
}
function Card({ title, content, isMobile }) {
return (
<div>
<Title>{title}</Title>
<Content>{content}</Content>
{isMobile && <Footer />}
</div>
)
}
随后的某一天,小张接手了这个项目,又有新需求:只有第偶数个 Card 才应该显示 Footer。于是,秉承着最小影响范围的原则,代码被改成了这样:
function PageA({ isMobile }) {
return (
<>
{/* ... */}
{listA.map(({ title, content }, index) => (
<Card title={title} content={content} isMobile={isMobile} index={index} />)
)}
</>
)
}
function PageB({ isMobile }) {
return (
<>
{/* ... */}
{listB.map(({ title, content }, index) => (
<Card title={title} content={content} isMobile={isMobile} index={index} />)
)}
</>
)
}
function Card({ title, content, isMobile, index }) {
return (
<div>
<Title>{title}</Title>
<Content>{content}</Content>
{isMobile && index % 2 === 1 && <Footer />}
</div>
)
}
随后的某一天,小王接手了这个项目,又有新需求。秉承着最小影响范围的原则 ......
分析原因
乍看之下,每次修改都是“局部最优”的,尽量修改最少的代码以限制影响范围,以确保在添加新功能时不引入错误。然而,实际上,由于每次“偷懒”,我们都违反了原则,导致代码变得越来越混乱。
原则
分离关注点原则(Separation of Concerns)是计算机科学和软件工程的基本设计原则之一,旨在帮助程序员更好地组织和管理复杂的系统。该原则的核心思想是将大型系统或程序分解为多个互相独立的组件,每个组件负责解决特定的关注点或任务,而不会受到其他关注点的干扰。这有助于提高代码的可维护性、可扩展性和可重用性。
重构
将上述原则应用于这个示例中:通用组件应该只了解与自身相关的信息,Card 组件只关心何时显示 Footer,而不关心它在何处使用以及是否为第偶数个。让我们重构代码:
function PageA({ isMobile }) {
return (
<>
{/* ... */}
{listA.map(({ title, content }, index) => (
<Card title={title} content={content} showFooter={isMobile && index % 2 === 1} />)
)}
</>
)
}
function PageB({ isMobile }) {
return (
<>
{/* ... */}
{listB.map(({ title, content }, index) => (
<Card title={title} content={content} showFooter={isMobile && index % 2 === 1} />)
)}
</>
)
}
function Card({ title, content, showFooter }) {
return (
<div>
<Title>{title}</Title>
<Content>{content}</Content>
{showFooter && <Footer />}
</div>
)
}
通过这次重构,我们成功解耦了通用组件和业务逻辑,使代码更易于维护和扩展。
如何编写难以维护的 React 代码?耦合通用组件与业务逻辑的更多相关文章
- 编写可维护的JavaScript代码(部分)
平时使用的时VS来进行代码的书写,VS会自动的将代码格式化,所有写了这么久的JS代码,也没有注意到这些点.看了<编写可维护的javascript代码>之后,做了些笔记. var resul ...
- 一步步教你编写不可维护的 PHP 代码
译者注:这是一篇很棒文章,使用有趣的叙述方式,从反面讲解了作为一个优秀的 PHP 工程师,有哪些事情是你不能做的.请注意哦,此篇文章罗列的行为,都是你要尽量避免的. 随着失业率越来越高,很多人意识到保 ...
- 编写可维护的js代码
在工作中,制定一套统一的编码风格,可以提高开发效率,维护起来的也要容易很多,也能避免一些不必要的错误出现. 项目中常用的检查编码风格的工具JSLint.JSHint.JSCS.ESLint,,在这呢, ...
- 编写可维护的javascript代码--- 2015.11.22(注释)
1.单行注释 // 这是一句单行注释 2.多行注释 /* 这里是代码 */ /* 这里都是注释 1232132 */ java的注释风格 /* * 另一段注释 * 这段注释包含2 ...
- 编写可维护的javascript代码--- 2015.11.21(基本格式化)
1.1 每行的编码需要控制在80字符. 1.2 改用:的地方必须用上. 1.3 缩进用2个制表符,不过4个也可以. 1.4 当代码一行显示不全需要折行显示,这里我暂且假定缩进为4个字符. 1.5 如果 ...
- 编写可维护的javascript代码---开篇(介绍自动报错的插件)
文章开篇主要推荐了2款检测编程风格的工具: JSLint和JSHint: jsLint是由Douglas Crockford创建的.这是一个通用的javascript代码质量检测工具,最开始JSLin ...
- 编写可维护的JavaScript代码
1. 1)for-in循环用来遍历对象属性.不仅遍历对象的实例属性,还遍历从原型继承来的属性. 所以最好使用hasOwnProperty()方法来过滤. 2) for in循环遍历出的对象属性不能保 ...
- 翻译 | 玩转 React 表单 —— 受控组件详解
原文地址:React.js Forms: Controlled Components 原文作者:Loren Stewart 译者:小 B0Y 校对者:珂珂君 本文涵盖以下受控组件: 文本输入框 数字输 ...
- 《代码不朽:编写可维护软件的10大要则(C#版)》读后感
本书作者Joost Visser,译者张若飞.本书讲解了编写可维护代码的10个要则,从目录就可以看出这10点分别是: 编写短小的代码单元(15行以内,在大部分情况下还是能实现的,但是当我们使用Linq ...
- 如何编写可维护的面向对象JavaScript代码
能够写出可维护的面向对象JavaScript代 码不仅可以节约金钱,还能让你很受欢迎.不信?有可能你自己或者其他什么人有一天会回来重用你的代码.如果能尽量让这个经历不那么痛苦,就可以节省不少时 间.地 ...
随机推荐
- The content of element type “web-app“ must match 解决方法
报错原因 问题描述 : 在创建 SpringMVC 时 , 选用 idea 的 webapp 模板来创建 , xml 配置文件中进行配置时发现提示警告 警告如下: 这错误大概的意思就是 ...
- 从实验中学习ResNet模型:在视频处理任务中取得显著进展
目录 引言 技术原理及概念 实现步骤与流程 示例与应用 优化与改进 结论与展望 "从实验中学习ResNet模型:在视频处理任务中取得显著进展" 在视频处理任务中,ResNet模型已 ...
- 写博文之必备技能MarkDown
前言 Markdown是一种轻量级标记语言,排版语法简洁,让人们更多地关注内容本身而非排版.它使用易读易写的纯文本格式编写文档,可与HTML混编,可导出 HTML.PDF 以及本身的 .md 格式的文 ...
- 组合数学_第4章_Polya定理
第4章 Polya定理 4.1 群的概念 4.1.1 群的定义 给定一个集合\(G=\{a,b,c,\cdots\}\)和集合\(G\)上的二元运算"\(\cdot\)",并满足下 ...
- 从GaussDB(DWS)的技术演进,看数据仓库的积淀与新生
摘要:随着云计算的兴起和渗透,云数仓成为了数仓技术演进的新阶段,并且逐渐成为了众多企业的共同选择. 本文分享自华为云社区<从GaussDB(DWS)的技术演进,看数据仓库的积淀与新生>,作 ...
- Profinet转EtherNet/IP网关连接AB PLC的应用案例
西门子S7-1500 PLC(profinet)与AB PLC以太网通讯(EtherNet/IP).本文主要介绍捷米特JM-EIP-PN的Profinet转EtherNet/IP网关,连接西门子S7- ...
- 脱发秘籍:前端Chrome调试技巧汇总
Chrome浏览器调试工具的核心功能: 注:本文测试.截图均为Edge浏览器(内核是Chromium),浏览器内核可了解<有哪些浏览器/内核?> 00.基础操作汇总 操作类型 快捷键/说明 ...
- 相较于Scrum, 我更推崇精益Kanban,帮助团队建立价值交付流,识别瓶颈问题
最近在学习实践精益Kanban方法,结合自己团队实践Srum的经历,整理些资料二者的差异.相较于Scrum, 我更推崇精益Kaban. Agile是一套理论和原则,就像天边的北极星.Devops是一种 ...
- CF1794B Not Dividing题解
如果 \(a_i\) 可以整除 \(a_{i - 1}\),只要在 \(a_i\) 上 \(+1\) 即可,这样 \(a_i \bmod a_{i - 1} = 1\) 就满足题目要求了,如果这样算来 ...
- Day03_Java_作业
A:选择题 1.给出以下代码,请问表达式grade==70在以下两条语句中是否获得执行? boolean flag = false && grade == 70;//第一条语句 boo ...