React库的优势非常明显:创建复杂的交互用户界面非常简单。最大的特点是可以在不破坏其他组件的情况下,将组件直接组合在一起。即使是Facebook、Instagram、Pinterest这样的社交媒体巨头也大量使用React,同时通过谷歌Maps这样的大型API创造无缝的用户体验。
如果你正在用React构建一个应用程序,或是考虑将其用于即将开展的项目,那么本教程就是为你准备的。希望通过公开一些需要再三考虑的代码执行,来帮助你构建出色的React应用程序。
下面是React里会使应用程序崩溃的八种做法:
1. 在null上设置默认参数
这是一个令人毛骨悚然的陷阱,可以让开发人员全线崩溃。毕竟,应用程序崩溃不是小事——任何类型的崩溃如果处理不当,随时都可能导致资金损失。
比如:
在应用程序组件中,如果日期最终是falsey,它将初始化为null。直觉告诉我们,在默认情况下,当项是一个falsey值时,应该将其初始化为空数组。但是当日期为falsey时,应用程序会崩溃,因为条目为空。
如果没有传递值或者未定义的值,那么默认函数参数允许使用默认值初始化已命名参数!
因此,下次将默认值设置为null时,一定要三思而后行。当空数组是值的预期类型时,可以将值初始化为空数组。
2. 用方括号抓取属性
有时抓取属性的方式可能会影响到应用程序的行为。也就是说会造成应用程序崩溃。下面是一个用方括号执行对象查找的例子:
这些实际上都是100%有效的用例,除了比对象键查找慢之外,实际上没有任何问题。无论如何,随着查找的深入,应用程序里也会出现问题:
如果你对此代码段实施某些增强并犯了一个小错误(例如将j中的J大写),结果将立即返回undefined,并且会发生崩溃:
令人毛骨悚然的部分是,应用程序会直到一部分代码尝试使用未定义值进行属性查找时才会崩溃。
所以在同一时间,joesProfile(经过伪装的未定义)将在应用程序运行,没有人会知道这个未定义值正在蔓延,直到一段代码执行属性查找,如joesProfile.age,因为joesProfile未定义!
为避免崩溃,一些开发人员会在查找不成功时初始化一些默认有效返回值:
至少现在,应用程序没有崩溃。这说明,当你使用方括号表示法应用查找时,往往是无效的。
然而,如果没有实际的例子,很难解释这种做法的严重性。所以,接下来我们举一个真实的例子。以将要展示的这个代码示例为例,它可以追溯到8个月前的存储库。为了保护这个代码来源的一些隐私,我们重名了几乎所有的变量,但是代码设计、语法和架构完全一样:
fixVideoTypeNaming是一个函数,它将根据作为参数传入的值提取视频类型。如果参数是一个视频对象,它将从.videoType属性中提取视频类型。如果是字符串,则调用者传入videoType,这样就可以跳过第一步。有人发现视频类型.mp4property在应用程序的几块地方都被拼错了。用fixVideoTypeNaming来快速修补这个错误。
现在,这个应用程序是用Redux构建的——因此语法。
要使用这些选择器,你可以导入到connect高阶组件中,以附加一个组件来侦听状态的那部分。
UI组件
该组件接收HOC传递给它的所有属性,并显示适应属性里的数据的信息。理想状态下可行,现实中只是暂时可行。 如果回到容器中,看看选择器是怎么选择它们的值的,其实可能已经埋下了一个定时炸弹,正在等着爆炸:
在开发任何类型的应用程序时,为了确保较高的可信度和减少开发流程中的漏洞,一般在开发过程中进行测试,以保证应用程序按预期运行。 然而,在这些代码片段的案例中,如果没有经过测试,而且没有及早处理,应用程序就会崩溃。例如,state、app、media、video、videoType是链的四个层次。
如果一个开发人员在修复应用程序的另一部分时不小心出错了,而state、app、media、video变成未定义状态,那么应用程序将崩溃,因为它无法读取未定义的videoType的属性。
此外,如果videoType出现了另外一个错误,而fixVideoTypeNaming没有更新以适应mp3的问题,那么该应用程序将面临另一个意外崩溃的风险。而这除非发生在真实的用户身上,否则没人能够检测到它。那时就为时已晚了。 绝不可以侥幸认为应用程序永远不会碰到这样的漏洞。请小心点!
3. 渲染时粗心地检查空对象
在过去有条件地渲染组件的黄金时期,有人曾做过一件事,那就是检查数据是否使用Object.keys填充到对象中。如果有数据,那么如果条件通过,组件将继续渲染。
假设调用了某个API,并在响应的某个地方接收了作为对象的项。话虽如此,乍一看似乎完全没有问题。项目的预期类型是对象,所以用Object.keys完全没问题。毕竟,如果出现错误并转化为falsey值,的确可以通过把项初始化为空对象来进行防御。
但服务器不总是返回相同的结构。如果将来项变成数组会怎样?Object.keys(items)不会崩溃,但会返回一个奇怪的输出,比如[“0”、“1”、“2”]。被该数据渲染的组件该如何反应呢?
但这还不是最糟的部分。代码片段中最糟的是,如果属性里收到的项是空值,那么项甚至不会初始化为默认值。
那么在开始使用应用程序前,就崩溃了:
再说一遍,请小心点!
4. 在渲染前粗心地检查数组是否存在
这可能和第3条的情况非常相似,但是数组和对象经常可以互换使用,所以应该单列出来。
如果你有这样做的习惯:
那么至少确保有单元测试,始终密切关注这段代码,或者在传递给渲染函数前及早正确地处理arr,否则如果arr变成对象文字,应用程序就会崩溃。当然, &&操作符会认为它是真实的,并尝试.map对象文字,这最终导致整个应用程序的崩溃。
所以请牢记于心。节省你的精力以及挫败感,把它留给更值得你特别关注的大问题吧!
5. 没有使用Linter
如果在开发应用程序时,没有使用任何类型的linter,或者根本不知道它们是什么,你必须知道为什么它们在开发中很有用。
用来辅助开发流程的linter是ESLint(https://eslint.org/?source=post_page---------------------------),这是一个著名的JavaScript的linting工具,它允许开发人员在不执行代码的情况下发现问题。
这个工具非常有用,它就像半个导师一样,及时纠正错误——就好像有人在指导你一样。它甚至描述了为什么你的代码可能是错误的,并建议你应该做什么。
这里有一个例子:
关于ESLint最酷的是,如果不喜欢某些规则或是不同意其中的一些规则,可以禁用这些规则,这样它们就不会在开发时显示为 linting警告/错误了。
6. 在渲染列表时进行解构
过去有些人出现过这种情况,而且很难检测到漏洞。基本上,如果有一个项目列表,并且准备渲染每个项目的一堆组件,如果列表中有一个项目不是期待值,那么应用程序会出现漏洞。如果应用程序不知道如何处理值类型,就有可能会崩溃。
这里有一个例子:
代码可以成功地运行。来看看API调用,而不是返回这个——
——如果在API客户端出现了意外情况并且返回这个数组时,如何解决这个问题呢?
那么应用程序就会崩溃,因为它不知道如何处理:
- Uncaught TypeError: Cannot read property 'name' of undefined
- at eval (DataList.js? [sm]:65)
- at Array.map (<anonymous>)
- at DataList (DataList.js? [sm]:64)
- at renderWithHooks (react-dom.development.js:12938)
- at updateFunctionComponent (react-dom.development.js:14627)
所以为了防止应用崩溃,可以在每次迭代中都设置一个默认对象:
现在,用户不会再对你的技术和专业知识评头论足了,因为他们不会再看到页面崩溃的情况了:
然而,即使应用不再崩溃,建议进一步处理缺失值,比如为具有类似问题的整个项目返回null,因为其中没有任何数据。
7. 没有充分研究你要实施的东西
不少人曾犯过这个致命的错误:对自己实施的搜索输入过度自信,过早相信自己的观点。
这是什么意思呢?搜索输入这一部分本应是个简单的任务——而且的确如此。整个搜索功能出现问题的真正原因是在查询中包含字符。
如果将关键字作为查询发送到搜索API,仅仅认为用户键入的每个键是有效的是不够的,即使是因为它们都在键盘上。
只要100%确保这样的正则表达式完全按预期运行,并避免遗漏任何可能使应用崩溃的无效字符:
该示例是搜索API最新的、既定的正则表达式。 以前它是这样的:
可以看到斜杠/不见了,而这导致了应用崩溃!如果该字符最终通过网络发送到API,猜猜API会如何处理URL?
另外,不要完全相信在网上找到的例子。其中有许多都不是经过充分测试的解决方案。而且就正则表达式而言,大多数用例没有真正的标准。
8. 不限制文件输入的大小
限制用户选择的文件大小是很好的做法,因为大多数情况下,如果不会出现任何品质损失,可以对大文件进行压缩。
但关于为什么把文件大小限制在某个限度内,还有一个更重要的原因。在公司里,用户上传图片时偶尔会被“冻结”。并不是每个人都有Alienware 17 R5电脑,所以必须考虑用户的特殊情况。
你不会希望用户在本应上传文件的时候却上传电子游戏吧?
以下是将文件限制为5 MB(5,000,000字节)限制的示例: