一份 2.5k star 的《React 开发思想纲领》

大家好,我是若川。持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列

翻译自:https://github.com/mithi/react-philosophies[1] 2.5k star
原文作者:mithi[2]
已获作者授权

概要

  1. 介绍

  2. 最低要求

  3. 面向幸福设计

  4. 性能优化技巧

  5. 测试原则

🧘 0. 介绍

《React 开发思想纲领》是:

  • 我开发 React 时的一些思考

  • 每当我 review 他人或自己的代码时自然而然会思考的东西

  • 仅仅作为参考和建议,并非严格的要求

  • 会随着我的经验不断更新

  • 大多数技术点是基础的重构方法论SOLID 原则以及极限编程等思想的变体,仅仅是在 React 中的实践而已 🙂

你可能会觉得我写的这些非常基础。但以下示例都来自一些复杂大型项目的线上代码。

《React 开发思想纲领》的灵感来源于我实际开发中遇到的各种场景。

🧘 1. 最低要求

1.1 计算机比你更「智能」

  1. 使用 ESLint 来静态分析你的代码,开启 rule-of-hooksexhaustive-deps 这两个规则来捕获 React 错误。

  2. 开启 JS 严格模式吧,都 2202 年了。

  3. 直面依赖,解决在useMemouseCallbackuseEffectexhaustive-deps 规则提示的 warning 或 error 问题。可以将最新的值挂在 ref 上来保证这些 hook 在回调中拿到的都是最新的值,同时避免不必要的重新渲染。

  4. 使用 map 批量渲染组件时,都加上 key

  5. 只在最顶层使用 hook,不要在循环、条件或嵌套语句中使用 hook。

  6. 理解不能对已经卸载的组件执行状态更新的控制台警告。

  7. 给不同层级的组件都添加错误边界(Error Boundary)来防止白屏,还可以用它来向错误监控平台(比如 Sentry)上报错误,并设置报警。

  8. 不要忽略了控制台中打印的错误和警告。

  9. 记得要 tree-shaking!

  10. 使用 Prettier 来保证代码的格式化一致性!

  11. 使用 TypescriptNextJS这样的框架来提升开发体验。

  12. 强烈推荐 Code Climate(或其他类似的)开源库。这类工具会自动检测代码异味(Code Smell,代码中的任何可能导致深层次问题的症状),它可以促使我去处理项目里留下的技术债。

1.2 Code is just a necessary evil

译者注:程序员的目标是解决客户的问题,代码只是副产品

1.2.1 先思考,再加依赖

依赖加的越多,提供给浏览器的代码就越多。扪心问问自己,你是否真的使用了某个库的 feature?

🙈  你真的需要它吗? 看看这些你可能不需要的依赖

  1. 你是否真的需要 Redux?有可能需要,但其实 React 本身也是一个状态管理库

  2. 你是否真的需要 Apollo clientApollo client 有许多很强大的功能,比如数据规范化。但使用的同时也会显著提高包体积。如果你的项目使用的并非是 Apollo client 特有的 feature,可以考虑使用一些轻量的库来替代,比如 react-querySWR(或者根本不用)。

  3. Axios 呢?Axios 是一个很棒的库,它的一些特性不容易通过原生的 fetch API 来复刻。但是如果使用 Axios 只是因为它有更好的 API,完全可以考虑在 fetch 上做一层封装(比如 redaxios 或自己实现)。取决于你的 App 是否真正地使用了 Axios 的核心 feature。

  4. Decimal.js 呢?或许 Big.js 或者其他轻量的库就足够了。

  5. Lodash/underscoreJS呢?推荐你看看【你不需要系列之“你不需要 Lodash/Underscore”】[3]

  6. MomentJS呢?【你不需要系列之“你不需要 Momentjs”】[4]

  7. 你不需要为了主题(浅色/深色模式)而使用 Context,考虑下用 css 变量 代替。

  8. 你甚至不需要 Javascript,CSS 也足够强大。【你不需要系列之“你不需要 JavaScript”】[5]

1.2.2 不要自作聪明,提前设计

"我们的软件在未来会如何迭代?可能会这样或者那样,如果在当下就开始往这些方向进行代码设计,这就叫 future-proof(防过时,面向未來编程)。"

不要这样搞! 应该在面临需求的时候再去实现相应功能,而不是在你预见到可能需要的时候。代码应该越少越好!

1.3 发现了就优化它

1.3.1 检测代码异味(Code Smell),并在必要时对其进行处理。

当你意识到某个地方出现了问题,那就马上处理掉。但如果当前不容易修复,或者没有时间,那请至少添加一条注释(FIXME 或者 TODO),附上对该问题的简要描述。来让项目里的每个人都知道这里有问题,让他们意识到当他们遇到这样的情况时也该这样做。

🙈 来看看这些容易发现的代码异味

  • ❌ 定义了很多参数的函数或方法

  • ❌ 难以理解的,返回 Boolean 值的逻辑

  • ❌ 单个文件中代码行数太多

  • ❌ 在语法上可能相同(但格式化可能不同)的重复代码

  • ❌ 可能难以理解的函数或方法

  • ❌ 定义了大量函数或方法的类/组件

  • ❌ 单个函数或方法中的代码行数太多

  • ❌ 具有大量返回语句的函数或方法

  • ❌ 不完全相同但代码结构类似的重复代码(比如变量名可能不同)

切记,代码异味并不一定意味着代码需要修改,它只是告诉你,你应该可以想出更好的方式来实现相同的功能。

1.3.2 无情的重构。简单比复杂好。

💁‍♀️ 小技巧: 简化复杂的条件语句,最好能提前 return。

🙈 提前 return 的示例

# ❌ 不太好if (loading) {return <LoadingScreen />
} else if (error) {return <ErrorScreen />
} else if (data) {return <DataScreen />
} else {throw new Error('This should be impossible')
}# ✅ 推荐if (loading) {return <LoadingScreen />
}if (error) {return <ErrorScreen />
}if (data) {return <DataScreen />
}throw new Error('This should be impossible')

💁‍♀️ 小技巧: 比起传统的循环语句,链式的高阶函数更优雅

如果没有明显的性能差异,尽量使用链式的高阶函数(map, filter, find, findIndex, some等) 来代替传统的循环语句。

1.4 你可以做的更好

💁‍♀️ 小技巧: 可以在 setState 时传入回调函数,所以没必要把 state 作为一个依赖项

你不用把 setStatedispatch 放在 useEffectuseCallback 这些 hook 的依赖数组中。ESLint 也不会给你提示,因为 React 已经确保了它们不会出错。

# ❌ 不太好
const decrement = useCallback(() => setCount(count - 1), [setCount, count])
const decrement = useCallback(() => setCount(count - 1), [count])# ✅ 推荐
const decrement = useCallback(() => setCount(count => (count - 1)), [])

💁‍♀️ 小技巧: 如果你的 useMemouseCallback 没有任何依赖,那你可能用错了

# ❌ 不太好
const MyComponent = () => {const functionToCall = useCallback(x: string => `Hello ${x}!`,[])const iAmAConstant = useMemo(() => { return {x: 5, y: 2} }, [])/* 接下来可能会用到 functionToCall 和 iAmAConstant */
}# ✅ 推荐
const I_AM_A_CONSTANT =  { x: 5, y: 2 }
const functionToCall = (x: string) => `Hello ${x}!`
const MyComponent = () => {/* 接下来可能会用到 functionToCall 和 I_AM_A_CONSTANT */
}

💁‍♀️ 小技巧: 巧用 hook 封装自定义的 context,会提升 API 可读性

它不仅看起来更清晰,而且你只需要 import 一次,而不是两次。

❌ 不太好

// 你每次需要 import 两个变量
import { useContext } from 'react';
import { SomethingContext } from 'some-context-package';function App() {const something = useContext(SomethingContext); // 看起来 ok,但可以更好// ...
}

✅ 推荐

// 在另一个文件中,定义这个 hook
function useSomething() {const context = useContext(SomethingContext);if (context === undefined) {throw new Error('useSomething must be used within a SomethingProvider');}return context;
}// 你只需要 import 一次
import { useSomething } from 'some-context-package';function App() {const something = useSomething(); // 看起来会更清晰// ...
}

💁‍♀️ 小技巧: 在写组件之前,先思考该怎么用它

设计 API 很难,README 驱动开发(RDD)是个很有用的办法,可以帮助你设计出更好的 API。并不是说应该无脑使用 RDD,但它背后的思想是很值得学习的。我自己发现,在设计实现组件 API 之前,使用 RDD 通常比不用时设计地更好。

🧘 2. 面向幸福设计

太长不看版

  1. 💖 通过删除冗余的状态来减少状态管理的复杂性。

  2. 💖 “传递香蕉,而不是拿着香蕉的大猩猩和整个丛林“(意思是组件要什么传什么,不要传大对象)。

  3. 💖 让你的组件小而简单 —— 单一职责原则。

  4. 💖 复制比错误的抽象要“便宜”的多(避免提早/不恰当的设计)。

  5. 避免 prop 层层传递(又叫 prop 钻取,prop drilling)。Context 不是解决状态共享问题的银弹。

  6. 将巨大的 useEffect 拆分成独立的小 useEffect

  7. 将逻辑提取出来都放到 hook 和工具函数中。

  8. useCallback, useMemouseEffect 依赖数组中的依赖项最好都是基本类型。

  9. 不要在 useCallback, useMemouseEffect 中放入太多的依赖项。

  10. 为了简单起见,如果你的状态依赖其他状态和上次的值,考虑使用 useReducer,而不是使用很多个 useState

  11. Context 不一定要放在整个 app 的全局。把 Context 放在组件树中尽可能低的位置。同样的道理,你的变量,注释和状态(和普通代码)也应该放在靠近他们被使用的地方。

💖 2.1 删除冗余的状态来减少状态管理的复杂性

冗余的状态指可以通过其他状态经过推导得到的状态,不需要单独维护(类似 Vue computed),当你有冗余的状态时,一些状态可能会丢失同步性,在面对复杂交互的场景时,你可能会忘记更新它们。

删除这些冗余的状态,除了避免同步错误外,这样的代码也更容易维护和推理,而且代码更少。

💖 2.2 “传递香蕉,而不是拿着香蕉的大猩猩和整个丛林“

为了避免掉入这种坑,最好将基本类型(boolean, string, number 等)作为 props 传递。(传递基本类型也能更好的让你使用 React.memo 进行优化)

组件应该仅仅只了解和它运作相关的内容就足够了。应该尽可能地与其他组件产生协作,而不需要知道它们是什么或做什么。

这样做的好处是,组件间的耦合会更松散,依赖程度会更低。低耦合更利于组件修改,替换和移除,而不会影响其他组件。

💖 2.3 让你的组件小而简单

什么是「单一职责原则」?

一个组件应该有且只有一个职责。应该尽可能的简单且实用,只有完成其职责的责任。

具有各种职责的组件很难被复用。几乎不可能只复用它的部分能力,很容易与其他代码耦合在一起。那些抽离了逻辑的组件,改起来负担不大而且复用性更强。

如何判断一个组件是否符合单一职责?

可以试着用一句话来描述这个组件。如果它只负责一个职责,描述起来会很简单。如果描述中出现了“和“或“或”,那么这个组件很大概率不是单一职责的。

检查组件的 state,props 和 hooks,以及组件内部声明的变量和方法(不应该太多)。问问自己:是否这些内容必须组合到一起这个歌组件才能工作?如果有些不需要,可以考虑把它们抽离到其他地方,或者把这个大组件拆解成小组件。

🧘 3. 性能优化技巧

  1. 如果你觉得应用速度慢,就应该做一次基准测试(benchmark)来证明。 "面对模凌两可的情况,拒绝猜测。" 多使用 Chrome 插件 - React 开发者工具的 profiler!

  2. useMemo 主要用在大开销的计算上。

  3. 如果你打算使用 React.memo, useMemo, 和 useCallback 来减少重新渲染,它们不该有过多的依赖项,且这些依赖项最好都是基本类型。

  4. 确保你清楚代码里 React.memo, useCallbackuseMemo 它们都是为了什么而使用的(是否真的能防止重新渲染?是否能证明在这些场景中真的可以显著提高性能? Memoization 有时会起到反作用,所以需要关注!)

  5. 优先修复慢渲染,再修复重新渲染。

  6. 把状态尽可能地放在它被使用的地方,一方面让代码读起来更顺,另一方面,能让你的 app 更快(state colocation(状态托管))

  7. Context 应该按逻辑分开,不要在一个 provider 中管理多个 value。如果其中某个值变化了,所有使用该 context 的组件(即便没有用到这个值),都会重新渲染。

  8. 可以通过拆分 statedispatch 来优化 context

  9. 了解下 lazy loading(懒加载)bundle/code splitting(代码分割)

  10. 长列表请使用 tannerlinsley/react-virtual 或其它类似的库。

  11. 包体积越小,app 越快。你可以使用 source-map-explorer 或者 @next/bundle-analyzer(用于 NextJS) 来进行包体积分析。

  12. 关于表单的库,推荐使用 react-hook-forms,它在性能和开发体验各方面都做的比较好。

🧘 4. 测试原则

  1. 测试应该始终与软件的使用方式相似。

  2. 确保不是在测试一些边界细节(用户不会使用,看不到甚至感知不到的内容)。

  3. 如果你的测试不能让你对自己的代码产生信任,那测试就是无意义的。

  4. 如果你正在重构某个代码,且最后实现的功能都是完全一致的,其实几乎不需要修改测试,而且可以通过测试结果来判定你正确的重构了。

  5. 对于前端来说,不需要 100% 的测试覆盖率,70% 就足够了。测试应该提升你的开发效率,虽然维护测试会暂时地阻塞你目前的开发,但当你不断地增加测试,会在不同阶段得到不同的回报。

  6. 我个人喜欢使用 JestReact testing libraryCypress,和 Mock service worker

End

翻译的不好,请大家见谅。如有任何想法,欢迎评论交流

参考资料

[1]

https://github.com/mithi/react-philosophies: https://github.com/mithi/react-philosophies

[2]

mithi: https://github.com/mithi

[3]

【你不需要系列之“你不需要 Lodash/Underscore”】: https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

[4]

【你不需要系列之“你不需要 Momentjs”】: https://github.com/you-dont-need/You-Dont-Need-Momentjs

[5]

【你不需要系列之“你不需要 JavaScript”】: https://github.com/you-dont-need/You-Dont-Need-JavaScript

d31918a93a1031165c66986a39daf8ef.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经坚持写了8年,点击查看年度总结。
同时,最近组织了源码共读活动,帮助3000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

7b6eb7654de883df2e88d8ace93b9dc9.png

扫码加我微信 ruochuan02、拉你进源码共读

今日话题

略。分享、收藏、点赞、在看我的文章就是对我最大的支持~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/274805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文案写作软件_11种可改善网站用户体验的文案写作技术

文案写作软件Written by John Stevens约翰史蒂文斯 ( John Stevens)撰写 When we talk about user experience and your website, it is easy to get caught up in the site’s design and navigation options. While that is important, the words you place on the page are…

张小龙谈用户体验

原文&#xff1a;http://sd.csdn.net/a/20120510/2805483.html从Foxmail到腾讯“七星级产品”QQ邮箱&#xff0c;再到腾讯核武器级产品微信。在外界看来&#xff0c;腾讯副总裁、广州研发部总经理张小龙作风低调&#xff0c;很少接受正式的媒体采访。然而作为当今国内最优秀的产…

web开发集成数字证书_每个数字设计师都应该知道的Web开发的七个原则

web开发集成数字证书A career path into digital design is often winding, meaning many practitioners come from adjacent fields as diverse as graphic design, web development, research, or even anthropology. As a result, two people working in a similar role may…

前端工程师生产环境 debugger 技巧

大家好&#xff0c;我是若川。持续组织了6个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列导言开…

figma设计_Figma与Adobe XD:我们如何选择下一个设计工具

figma设计The time came for changes and our design team started raising the topic again about how we should consider moving away from Sketch. This is not the first time this question came to mind, but this time seems like it was serious. Last summer we cons…

一个小厂前端 Leader 如何筛选候选人?

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列本文作…

figma设计_如何在Figma中构建设计入门套件(第1部分)

figma设计Figma教程 (Figma Tutorial) Do you like staring at a blank canvas every time you start a new project in Figma?每次在Figma中启动新项目时&#xff0c;您是否喜欢盯着一块空白的画布&#xff1f; I’m guessing you’re not a big fan right, but it’s a pra…

纯靠技术,很难进入大厂了。。。

日前&#xff0c;国务院印发《“十四五”时期就业促进规划的通知》&#xff0c;其中明确指出&#xff0c;要完善终身学习体系&#xff0c;推进高水平大学开放教育资源&#xff0c;畅通在职人员继续教育与终身学习通道。为响应国家政策&#xff0c;现临时扩大招生规模&#xff0…

十天学会ASP.Net——(8)

1. ajax入门AJAX Extensions工具箱 &#xff08;1&#xff09;实现又刷新改变字体大小和无刷新改变字体大小 页面设计&#xff1a; 前台页面设计&#xff1a; 首先需要在用到ajaxExtensions控件的位置之前放置一个ScriptManager控件&#xff0c;它将在浏览页面时不可见&#xf…

聊聊 computed 影响性能的场景

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列前言在…

saej1929_(1929年-2020年)

saej1929Milton Glaser, the legendary graphic designer who co-founded New York Magazine, created the iconic ‘I ❤ NY’ logo, the psychedelic Bob Dylan poster, and the Brooklyn Brewery logo, passed away yesterday at the age of 91 on his birthday, June 26, 2…

Chap2-构造函数语意学

如果一个类没有任何constructor&#xff0c;那么会有一个default constructor被隐式的声明出来&#xff0c;一个implicit default constructor将是一个trivial&#xff08;无用的&#xff09;constructor。但是在某些情况下&#xff0c;implicit default constructor将是一个no…

【热点】React18正式版发布,未来发展趋势是?

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列2022年…

不要重新发明轮子_是否重新发明轮子

不要重新发明轮子Design is a profession that thrives on creativity. Us designers are constantly trying to innovate by thinking outside the box. We’ve seen design evolve across all sectors — print, digital, product, architecture etc. We have gone from type…

点击页面元素,这个Vite插件竟然帮我打开了Vue组件文件!超级好用!

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列前言这…

shields 徽标_符号,标志,文字标记:徽标类型的综合指南

shields 徽标Designers and non-designers alike struggle with common terminology when talking about brand marks, often using different terms interchangeably. When it comes to clarifying definitions, sometimes even the most seasoned professionals get confused…

React 18 带给我们的惊喜

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列这篇文…

建模心法(2)——迈出建模第一步

原文地址&#xff1a;http://www.cnblogs.com/1-2-3/archive/2008/08/04/model-method-part1.html 原文作者&#xff1a;景春雷 一错再错的这故事才精彩 ——朴树 《我爱你再见》摘要 即使读了再多的书、跟过再多的项目&#xff0c;…

Web:你知道我这十几年是怎么过来的吗?!

大家好&#xff0c;我是若川。持续组织了8个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列1989 …

设计师更高效_如何丢掉我的工作使我成为一名更好的设计师

设计师更高效I lost my job a few times early on in my design career. In the process of getting back up after a job loss, it has made me a better designer not only in terms of hard skills but the soft skills required to be more resilient and empathetic, whic…