ReactJS的最佳编码详细指南

124 阅读8分钟

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。点击这里查看原文。