React一直是构建Web应用时创建用户界面的最流行的库之一。它被许多公司广泛使用,并拥有一个活跃的社区。
作为一个React开发者,了解这个库的工作原理并不是你建立用户友好、易于扩展和可维护的项目的唯一需要。
了解某些惯例也是必要的,这将使你能够编写干净的React代码。这不仅能帮助你更好地服务于你的用户,还能让你和其他从事项目的开发者更容易维护代码库。
在本教程中,我们将首先讨论React开发人员面临的一些常见挑战,然后深入探讨一些你可以遵循的最佳实践,以帮助你以更有效的方式编写React代码。
React开发者面临的挑战
在本节中,我们将讨论React开发者在构建Web应用期间和之后所面临的一些主要挑战。
你在本节中看到的所有挑战都可以通过遵循最佳实践来避免,我们将在后面详细讨论。
我们将从影响初学者的最基本问题开始。
React的先决条件
React开发者面临的主要挑战之一是了解该库如何工作,以及使用它的先决条件。
在学习React之前,你需要知道一些事情。由于React使用JSX,所以了解HTML和JavaScript是必须的。当然,你也应该知道CSS或现代CSS框架来设计你的网络应用。
特别是,在深入研究React之前,你应该知道一些核心的JavaScript概念和功能。其中一些,大多属于ES6,包括:
- 箭头函数
- 休止符
- 扩展运算符
- 模块
- 去结构化
- 阵列方法
- 模板字词
- 承诺
let
和const
变量
上面列出的JavaScript主题将帮助你作为一个初学者理解React的工作原理。
你还会了解到React中的新概念,比如:
- 组件
- JSX
- 状态管理
- Props
- 渲染元素
- 事件处理
- 条件性渲染
- 列表和键
- 表格和表格验证
- 钩子
- 样式设计
对React概念和使用该库的先决条件有一个扎实的了解,将有助于你有效地利用其功能。
但不要让这些压倒你。通过不断的练习和学习,你可以迅速掌握如何使用React来构建令人敬畏的项目。这类似于学习一种新的编程语言–它只是需要一点时间和实践来理解。
状态管理
在React中更新你的变量的状态/值的工作方式与你使用普通JavaScript的方式不同。
在JavaScript中,更新一个变量就像使用等价运算符(=
)给它分配一个新值一样简单。下面是一个例子:
var x = 300; function updateX(){ x = 100; } updateX(); console.log(x); // 100
在上面的代码中,我们创建了一个名为 x
的变量,初始值为 300
。
使用等于运算符,我们为其指定了一个新值 100
。这是在 updateX
函数中编写的。
在React中,更新变量的状态/值的工作方式不同。以下是操作方法:
import { useState } from 'react'; function App() { const [x, setX] = useState(300) let updateX =()=>{ setX(100); } return ( <div className="App"> <h1>{x}</h1> <button onClick={updateX}>Update X</button> </div> ); } export default App;
当更新React中变量的状态时,可以使用 useState
钩子。使用此钩子时需要注意三点:
- 变量名称
- 用于更新变量的函数
- 变量的初始值/状态
在我们的示例中,x
是变量的名称,setX
是用于更新 x
值的函数,而 x
的初始值(300
)作为参数传递给 useState
函数:
const [x, setX] = useState(300)
为了更新 x
的状态,我们使用了 setX
函数:
import { useState } from 'react'; let updateX =()=>{ setX(100); }
所以 updateX
函数调用了 setX
函数,然后将 x
的值设置为 100
。
虽然这对于更新你的变量的状态似乎是完美的,但在非常大的项目中,它增加了你的代码的复杂性。拥有大量的状态钩子使得代码非常难以维护和理解,特别是当你的项目规模扩大时。
使用状态钩子的另一个问题是,创建的这些变量不能在组成你的应用程序的不同组件之间共享。你仍然必须使用Props来将数据从一个变量传递到另一个变量。
幸运的是,我们有一些库可以在React中有效地处理状态管理。它们甚至允许你创建一次变量,并在你的React应用中的任何地方使用它。这些库中的一些包括Redux、Recoil和Zustand。
选择第三方库进行状态管理的问题是,你将被迫学习与你在React中已经学过的东西相异的新概念。例如,Redux以有大量的模板代码而闻名,这使得初学者难以掌握(尽管这一点正在被Redux Toolkit修复,它让你写的代码比Redux少)。
可维护性和可扩展性
随着产品的用户需求不断变化,总是需要对构成产品的代码进行修改。
如果你的代码对团队来说不容易维护,那么你的代码往往很难扩展。诸如此类的困难来自于编写代码时遵循的不良做法。他们一开始可能看起来工作得很完美,给你带来了想要的结果,但是任何 “现在 “有效的东西对于你项目的未来和发展来说都是低效的。
在下一节中,我们将介绍一些惯例,这些惯例可以帮助改善你写React代码的方式。这也将帮助你在与专业团队合作时更好地进行协作。
React最佳实践
在这一节中,我们将谈论一些编写React代码时需要遵循的最佳实践。
1. 保持清晰的文件夹结构
文件夹结构有助于你和其他开发者了解项目中使用的文件和资产的安排。
有了一个好的文件夹结构,就可以很容易地浏览,节省时间并帮助避免混乱。文件夹结构因每个团队的偏好而不同,但这里有一些React中常用的文件夹结构。
按功能或路线对文件夹进行分组
根据路线和功能对文件夹中的文件进行分组,有助于将关于某个特定功能的所有内容放在一个空间中。例如,如果你有一个用户仪表盘,你可以把与仪表盘有关的JavaScript、CSS和测试文件放在一个文件夹中。
下面是一个例子来证明:
dashboard/ index.js dashboard.css dashboard.test.js home/ index.js Home.css HomeAPI.js Home.test.js blog/ index.js Blog.css Blog.test.js
从上面可以看出,应用程序的每个核心功能的所有文件和资产都存储在同一个文件夹中。
分组类似的文件
另外,你也可以将类似的文件分组在同一个文件夹中。你也可以为Hooks、组件等设置单独的文件夹。请看这个例子:
hooks/ useFetchData.js usePostData.js components/ Dashboard.js Dashboard.css Home.js Home.css Blog.js Blog.css
编码时,你不必严格遵循这些文件夹结构。如果你有一个特定的方式来排列你的文件,去吧。只要你和其他开发者对文件结构有一个清晰的认识,你就可以开始了
2. 建立一个结构化的导入顺序
随着你的React应用程序的不断增长,你一定会做额外的导入。导入文件的结构在帮助你理解组成你的组件方面有很大的作用。
作为一种惯例,将类似的实用程序组合在一起似乎效果不错。例如,你可以将外部或第三方导入与本地导入分开。
请看下面的例子:
import { Routes, Route } from "react-router-dom"; import { createSlice } from "@reduxjs/toolkit"; import { Menu } from "@headlessui/react"; import Home from "./Home"; import logo from "./logo.svg"; import "./App.css";
在上面的代码中,我们首先将第三方库分组(这些是我们必须事先安装的库)。
然后我们导入了我们在本地创建的文件,如样式表、图片和组件。
为了简单和容易理解,我们的例子并没有描述一个非常大的代码库,但请记住,与这种导入格式保持一致将有助于你和其他开发人员更好地理解你的React应用程序。
你可以进一步根据文件类型对本地文件进行分组,如果这对你有用的话–也就是说,将组件、图片、样式表、Hooks等分别归入本地导入文件。
下面是一个例子:
import Home from "./Home"; import About from "./About" import Contact from "./Contact" import logo from "./logo.svg"; import closeBtn from "./close-btn.svg" import "./App.css"; import "Home.css"
3. 遵守命名惯例
命名约定有助于提高代码的可读性。这不仅适用于组件名称,甚至适用于变量名称,一直到Hooks。
React文档没有提供任何用于命名组件的官方模式。最常用的命名约定是camelCase和PascalCase。
PascalCase主要用于组件名称:
import React from 'react' function StudentList() { return ( <div>StudentList</div> ) } export default StudentList
上面的组件名为 StudentList
,它比 Studentlist
或 studentlist
更可读。
另一方面,camelCase命名约定主要用于命名变量、钩子、函数、数组等:
const [firstName, setFirstName] = useState("Ihechikara"); const studentList = []; const studentObject = {}; const getStudent = () => {}
4. 使用Linter
Linter工具有助于提高代码质量。最受欢迎的JavaScript和React的linter工具之一是ESlint。但这究竟是如何帮助提高代码质量的呢?
Linter工具有助于提高代码库的一致性。当使用像ESLint这样的工具时,你可以设置你希望每个在项目上工作的开发者都能遵守的规则。这些规则可能包括要求使用双引号而不是单引号,箭头函数周围的大括号,特定的命名惯例,以及更多。
该工具会观察你的代码,然后在规则被破坏时通知你。破坏规则的关键词或行通常会用红色下划线。
由于每个开发人员都有自己的编码风格,Linter工具可以帮助实现代码的统一。
Linter工具还可以帮助我们轻松修复错误。我们可以看到拼写错误,已声明但未使用的变量,以及其他此类功能。其中一些bug可以在你编码时自动修复。
像ESLint这样的工具是内置于大多数代码编辑器中的,所以你可以在旅途中获得linter功能。你还可以根据你的编码要求来配置它。
5. 使用片段库
使用一个拥有活跃社区的框架,最酷的事情是有很多工具被创造出来以使开发更容易。
插件库可以通过提供开发人员经常使用的预置代码,使开发更快。
一个很好的例子是ES7+ React/Redux/React-Native snippets扩展,它有很多有用的命令用于生成预置代码。例如,如果你想创建一个React功能组件,而不需要打出所有的代码,你使用该扩展所需要做的就是输入 rfce
并点击Enter。
上面的命令将继续生成一个功能组件,其名称与文件名相对应。我们使用ES7+ React/Redux/React-Native片段扩展生成了下面的代码。
import React from 'react' function StudentList() { return ( <div>StudentList</div> ) } export default StudentList
另一个有用的代码段工具是Tailwind CSS IntelliSense扩展,它简化了使用TailwindCSS设置网页样式的过程。该扩展可以通过建议实用程序类、语法高亮显示和缩进功能来帮助您自动完成。你甚至可以在编码时看到你的颜色。
6. 合并CSS和JavaScript
在处理大型项目时,为每个组件使用不同的样式表文件可能会使文件结构庞大且难以导航。
这个问题的解决方案是将CSS和JSX代码结合起来。您可以使用框架/库,如Tailwind CSS和Emotion。
以下是Tailwind CSS的样式:
<p className="font-bold mr-8">resource edge</p>
上面的代码为段落元素提供了粗体字体,并在右侧添加了一些边距。我们可以使用框架的实用程序类来实现这一点。
以下是您如何使用情感来设计元素的风格:
<h1 css={css` color: black; font-size: 30px; `} > Hello World! </h1>
7. 限制组件创建
React的核心特征之一是代码的可重用性。您可以创建一个组件并尽可能多次重用其逻辑,而无需重写该逻辑。
考虑到这一点,您应该始终限制创建的组件的数量。不这样做会使文件结构膨胀,因为不必要的文件本来就不应该存在。
我们将使用一个非常简单的示例来演示这一点:
function UserInfo() { return ( <div> <h1>My name is Ihechikara.</h1> </div> ); } export default UserInfo
上面的组件显示了用户的名称。如果我们为每个用户创建一个不同的文件,那么最终会有不合理的文件数量。(当然,我们使用用户信息来保持简单。在现实生活中,你可能需要处理不同类型的逻辑。)
为了使组件可重用,我们可以使用Props。以下是操作方法:
function UserInfo({userName}) { return ( <div> <h1>My name is {userName}.</h1> </div> ); } export default UserInfo
之后,我们可以导入该组件,并根据需要多次使用它:
import UserInfo from "./UserInfo"; function App() { return ( <div className="App"> <UserInfo userName={"Ihechikara"} /> <UserInfo userName={"John"} /> <UserInfo userName={"Jane"} /> </div> ); } export default App;
现在,我们有三个不同的 UserInfo
组件实例,它们来自在一个文件中创建的逻辑,而不是每个用户有三个单独的文件。
8. 实施延迟加载
随着React应用的增长,延迟加载非常有用。当你有一个大的代码库时,网页的加载时间会变慢。这是因为每个用户每次都必须加载整个应用程序。
“延迟加载”是用于各种实现的术语。在这里,我们将其与JavaScript和React相关联,但您也可以在图像和视频上实现延迟加载。
默认情况下,React捆绑并部署整个应用程序。但是我们可以使用延迟加载(也称为代码拆分)来改变这种行为。
基本上,您可以限制应用程序在某个特定点加载的部分。这是通过拆分捆绑包并仅加载与用户需求相关的捆绑包来实现的。例如,您可以首先仅加载用户登录所需的逻辑,然后仅在用户成功登录后才加载用户仪表板的逻辑。
9. 使用可重复使用的钩子
React中的钩子可以让你利用React的一些额外功能,比如与你的组件的状态进行交互,以及运行与你的组件中某些状态变化有关的后效。我们可以在不写类组件的情况下完成这一切。
我们还可以使Hooks可重复使用,这样我们就不必在每个使用它们的文件中重新输入逻辑。我们通过创建自定义Hooks来做到这一点,这些Hooks可以在应用程序的任何地方导入。
在下面的例子中,我们将创建一个用于从外部API获取数据的Hook:
import { useState, useEffect } from "react"; function useFetchData(url) { const [data, setData] = useState(null); useEffect(() => { fetch(url) .then((res) => res.json()) .then((data) => setData(data)) .catch((err) => console.log(`Error: ${err}`)); }, [url]); return { data }; } export default useFetchData;
我们已经创建了一个用于从上面的API中获取数据的Hook。现在它可以被导入到任何组件中。这样我们就不用在每个需要获取外部数据的组件中输入所有的逻辑了。
我们可以在React中创建的自定义Hooks的类型是无限的,所以由你来决定如何使用它们。只要记住,如果它是一个必须在不同的组件中重复使用的功能,你肯定应该让它可重复使用。
10. 记录和管理错误
在React中,有不同的方法来处理错误,如使用错误边界、尝试和捕捉块或使用外部库,如react-error-boundary。
React 16中引入的内置错误边界是类组件的功能,所以我们不会讨论它,因为我们建议你使用功能组件而不是类组件。
另一方面,使用 try
和 catch
区块只适用于指令性代码,而不是声明性代码。这意味着在使用JSX时,它不是一个好的选择。
我们最好的建议是使用一个像 react-error-boundary 这样的库。这个库提供的功能可以包裹在你的组件中,这将帮助你在React应用被渲染时检测错误。
11. 监控和测试你的代码
在开发过程中测试你的代码有助于你编写可维护的代码。不幸的是,这是很多开发者忽视的事情。
尽管许多人可能认为,在构建你的网络应用程序时,测试并不是什么大事,但它有无数的好处。以下是其中的一些:
- 检测错误会导致代码质量的提高。
- 单元测试可以被记录下来,用于数据收集和未来参考。
- 早期的错误检测为你节省了支付给开发人员的费用,以扑灭如果不加检查可能引起的火灾。
- 没有错误的应用程序和网站会赢得受众的信任和忠诚,从而带来更大的增长。
你可以使用Jest或React测试库等工具来测试你的代码。有很多测试工具供你选择–这一切都归结于最适合你的工具。
你也可以在构建React应用程序时,通过在浏览器中运行这些应用程序来测试它们。你通常会得到任何检测到的错误显示在屏幕上。这类似于使用DevKinsta开发WordPress网站–这个工具允许你在本地机器上设计、开发和部署WordPress网站。
12. 使用功能组件
在React中使用功能组件有很多好处。你写的代码更少,更容易阅读,官方React文档的测试版正在使用功能组件(Hooks)进行重写,所以你肯定应该习惯使用它们。
使用功能组件,你不必担心使用 this
或使用类。由于Hooks的存在,你还可以通过写更少的代码来轻松管理你的组件的状态。
你在React上找到的大多数更新的资源都使用了功能组件,当你遇到问题时,可以很容易地理解和遵循社区创建的有用指南和资源。
13. 跟上React版本变化的步伐
随着时间的推移,新的功能会被引入,而一些旧的功能会被修改。最好的方法是关注官方文档。
你也可以加入社交媒体上的React社区,在变化发生时获得相关信息。
保持对React当前版本的了解将有助于你确定何时优化或修改你的代码库以获得最佳性能。
还有一些围绕React建立的外部库,你也应该了解最新情况–比如React Router,它用于React的路由。了解这些库的变化可以帮助你对你的应用程序进行相关的重要修改,并使每个人在项目中的工作更容易。
此外,当新版本发布时,一些功能可能会被废弃,某些关键词可能会被改变。为了安全起见,在发生这种变化时,你应该始终阅读文档和指南。
14. 使用一个快速、安全的主机供应商
如果你想在建立你的网络应用程序后让每个人都能访问它,你就必须托管它。重要的是,你要使用一个快速和安全的托管供应商。
托管你的网站使你可以使用不同的工具,使你的网站的扩展和管理变得容易。托管你的网站的服务器使你本地机器上的文件有可能安全地存储在服务器上。托管你的网站的总体好处是,其他人可以看到你所创造的很棒的东西。
有各种平台为开发者提供免费的托管服务,如Firebase、Vercel、Netlify、GitHub Pages,或付费服务,如Azure、AWS、GoDaddy、Bluehost等。
小结
学习如何使用React并不是创建优秀网络应用的全部要求。就像Angular、Vue等其他框架一样,有一些你应该遵循的最佳实践,以帮助你构建高效的产品。
遵循这些React惯例不仅有助于你的应用程序,而且对你作为一个前端开发者也有好处–你学会了如何编写高效、可扩展和可维护的代码,而且你在你的领域中作为一个专业人士脱颖而出。
因此,当你用React构建你的下一个网络应用时,请牢记这些最佳实践,使你的用户和你的开发者都能轻松使用和管理产品。
你还知道哪些在本文中没有提到的React最佳实践?请在下面的评论中分享它们。
评论留言