ReactJS中的最佳编码实践
在这篇文章中,我们将讨论在你的下一个项目中可以遵循的最佳编码实践,以使代码干净、高效,并易于被另一个开发人员所适应。
简介
在这篇文章中,我们将讨论你在下一个项目中可以遵循的最佳编码实践。这些实践将使你的代码可重复使用、更干净、更高效,并且容易被另一个开发者所适应。
以下是我们今天要介绍的编码最佳实践的清单。
- 合并状态
- 在长的组件层次结构中使用useContext
- 将UI和逻辑分开
- 删除不必要的道具
- 为重复性的任务写一个函数
- 避免命名导入/成员导入
- 使用forEach而不是map
1.合并状态
在大多数组件中,你会有一个状态。在定义一个新的状态时,花点时间想想你是否可以将多个状态合并成一个状态。让我们在一个例子的帮助下理解这一点。假设你正在做一个巧克力网站,你有两种类型的尺寸。
**默认尺寸。**你将从API接收尺寸。
**自定义尺寸。**用户可以添加自定义尺寸。
一旦用户添加了自定义尺寸,他/她可以通过选择所需的尺寸来进行结账。在错误的编码实践中,你可以有三种不同的状态。
- 默认尺寸的状态(从后台收到的)。
- 自定义尺寸的状态
- 选择尺寸的状态
因此,你将不得不定义三种不同的状态。
const [APISizes, setAPISizes] = useState([{
id: ''
height: '',
width: ''
}]);
const [customSizes, setCustomSizes] = useState([{
id: '',
height: '',
width: ''
}]);
const [selectedSizes, setSelectedSizes] = useState([1, 2]);
现在你必须关注三个不同的状态,你需要让它们保持同步。让我们来看看会产生问题的情况。
在显示所有尺寸的时候,你必须循环浏览两个状态,包括APISizes和customSizes。
在selectedSizes中,我们只存储了id,但对于尺寸信息,我们必须遍历APISize和CustomSize。在良好的编码实践中,你可以定义一个单一的状态,如下所示。
const [userSuggestions, setUserSuggestion] = useState([{
id: 1,
height: 100,
width: 100,
isCustom: false,
isSelected: false
}]);
在这种情况下,你只需要考虑一个状态,如果其他开发人员在你的代码上工作,他/她也会很容易。此外,如果你想引入一个新的键,你只需要更新一个状态而不是2或3个状态。
const [userSuggestions, setUserSuggestion] = useState([{
id: 1,
height: 100,
width: 100,
isCustom: false,
isSelected: false,
isByDefaultSelected: true,
}]);
2.在长的组件层次结构中使用useContext
在一个长的组件层次结构中,useContext将提供更干净和可重复使用的代码。请看下面的例子。
在应用程序中,你可以选择一个项目和文件夹。在仪表盘组件中,我们想显示所选项目和文件夹的总数,为此我们需要在仪表盘组件中定义两个状态。
- 选定的项目
- 选定的文件夹
我们将从以下方面传递这些状态。
选定的项目仪表板 -> 项目 -> 项目显示 -> 项目选项。
选定的文件夹仪表板 -> 文件夹 -> 文件夹显示 -> 文件夹选项。
随着状态的数量和组件数量的增加,这个问题变得更加棘手。解决这个问题的方法是创建上下文。它将允许你在任何组件中使用状态。你将从最上面的组件调用上下文,所有的子组件都能使用状态。
如果你不知道上下文是如何工作的,你可以通过这篇文章。
3.分离逻辑和UI
最好是把逻辑和UI分开。例如,你可以把onClick函数写成一个内联函数,或者你可以调用一个单独的函数。创建一个单独的函数而不是写一个内联函数将使UI和逻辑之间有一个清晰的分离。这将使代码更容易理解,更清晰,更可重复使用。
4.删除不必要的道具
仔细观察你的道具是动态的还是静态的。除了静态道具外,有时我们把redux状态作为道具传递,这对减少渲染的数量没有任何帮助。将redux状态作为props传递,使得组件很难被重用。我们将借助一个例子来理解这一点。
在我们的项目中,我们有一个配置文件组件,配置文件组件被称为图像组件。图像组件需要登录用户信息,而登录用户信息被存储在redux状态中。简介组件已经在调用登录信息的redux状态。在这种情况下,你可以从两个选项中选择。
- 将redux状态作为props从父组件(Profile)传递给子组件(Image)。
- 使用useSelector在子组件(Image)中调用redux状态。
你应该总是选择第二个选项,因为在未来,Image组件将被多个组件使用。所有Image组件的父组件都必须调用登录用户信息。(因为登录用户信息是Image组件的必选道具)。这将导致每次组件被重用时都会不必要地调用redux状态。
在这两种情况下,如果你把状态作为道具从父组件(从profile到Image)传递,或者在子组件(Image组件)中使用useSelector,React会重新渲染。道具的变化会导致重新渲染,redux状态的变化也会导致重新渲染。
5.为一个重复的任务写一个函数
这似乎是一件很正常的事情,但是要注意重复性的代码。例如,你可能会以同样的方式从5个不同的组件更新相同的状态。在这种情况下,创建一个函数来更新状态,并在所有组件中使用该函数。当你写代码时要放慢速度,如果你发现自己一次又一次地写同样的代码,那么就应该写一个通用函数来代替。
我强烈建议为重复性的任务创建一个公共函数。当你写的代码越多,你就会越珍惜你写常用函数的时间。将来,如果你有任何代码变化,就只有一个地方可以修改代码,而不是通过所有的组件。
6.如果可能的话,避免命名导入/成员导入
首先,让我们了解一下如何导入模块。比方说,你正在使用material UI。在你的组件中,你需要来自material UI的Button和TextField。你可以通过两种方式导入它们。
1.命名导入/成员导入
import {TextField, Button} from "@mui/material";
2.默认导入
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
总是倾向于默认导入,因为在默认导入中只有按钮和文本框的代码被导入。在命名导入/成员导入中,所有的material UI模块都被加载。从所有的material UI代码中,你在你的组件中使用按钮和文本框。随着时间的推移,这将增加包的大小。默认导入有一个缺点,如果你使用10个不同的material UI组件,你将在一个文件中拥有10个不同的导入。
import CloseIcon from "@mui/icons-material/Close";
import AppBar from "@mui/material/AppBar";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Container from "@mui/material/Container";
import IconButton from "@mui/material/IconButton";
import Paper from "@mui/material/Paper";
import Popover from "@mui/material/Popover";
import TextField from "@mui/material/TextField";
import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
这将增加代码行数,但它将减少包的大小。
7.使用forEach而不是Map
在代码中,我们通常使用map来迭代一个对象。许多开发者遵循这种错误的做法。如果你只想对一个对象进行迭代,你必须使用forEach。如果你想修改当前对象,那么就使用map。
让我们通过一个例子来理解这个问题。假设我们有如下的尺寸对象。
sizes = {
category: '',
height: '',
width: '',
isSelected: false
}
1. forEach
我们想遍历超大的对象,以获得所有类型的尺寸类别到一个数组。我们不是在修改 sizes 对象,而是在迭代 oversized 对象以获得新的信息。
const allCategory = [];
sizes.forEach((sizeObj) => {
const {
category
} = sizeObj;
if (!allCategory.includes(category)) allCategory.push(category);
});
2.2.地图
在点击按钮时,我们想选择所有 "自定义 "类别的尺寸。在这种情况下,我们要修改尺寸对象。
const updatedSizes = sizes.map((sizeObj) => {
const {
category
} = sizeObj;
if (category === 'custom') {
const newSizeObj = {
...sizeObj,
isSelected: true,
};
return newSizeObj;
}
return sizeObj;
});
Map返回一个新的对象,所以在updateSizes中,所有'个人'类别的尺寸将被选中。以下是一些与变量相关的做法,你可以在编码时遵循。
- 使用const而不是let(如果可能)。
- 编写有意义的、更容易理解的变量名称
这就是全部!我希望你喜欢阅读这篇文章。
由Hitanshi Mehta授权发布于DZone。点击这里查看原文。