日常工作中需要避免的9个React坏习惯
前言
React是前端开发领域中最受欢迎的JavaScript库之一,但有时候在编写React应用程序时,可能陷入一些不佳的习惯和错误做法。这些不佳的习惯可能导致性能下降、代码难以维护,以及其他问题。在本文中,我们将探讨日常工作中应该避免的9个坏React习惯,并提供相关示例代码来说明这些问题以及如何避免它们。
1. 属性传递问题(Prop Drilling)
属性传递问题是一种常见的不良习惯,它发生在将属性从一个组件传递到多层嵌套的子组件时。这可能导致性能问题和代码可读性降低。理想情况下,应该尽量避免将属性传递超过2层。下面是一个示例:
// 父组件
function ParentComponent() {
const data = 'Some data';
return (
<ChildComponent data={data} />
);
}
// 子组件
function ChildComponent({ data }) {
return (
<GrandchildComponent data={data} />
);
}
// 孙子组件
function GrandchildComponent({ data }) {
// 使用数据
return <div>{data}</div>;
}
在上面的示例中,data属性通过多个嵌套层级传递,这可能导致性能问题和可读性问题。解决这个问题的方法之一是使用React的上下文(context)来共享数据,或者重新组织组件结构。
2. 导入过多所需的内容
在React应用程序中,导入过多的依赖项可能会导致包变得庞大,从而增加加载时间。在日常工作中,确保只导入需要的依赖项。例如,避免导入整个库,而只导入所需的功能。
// 不良示例 - 导入整个库
import _ from 'lodash';
// 良好示例 - 只导入所需的功能
import { someFunction } from 'lodash';
这有助于减小包的大小,提高应用程序性能。
3. 不将业务逻辑与组件逻辑分离
在React中,尽量将业务逻辑与UI组件逻辑分开,以提高代码的可读性和可维护性。将业务逻辑提取到独立的服务文件或模块中,以使组件保持简单。以下是一个示例:
// 不良示例 - 业务逻辑混杂在组件中
function UserProfile() {
const user = getUserData(); // 从API获取用户数据
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
// 良好示例 - 业务逻辑分离
function UserProfile() {
const user = useUserData(); // 从独立服务获取用户数据
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
通过将业务逻辑提取到独立的useUserData函数中,使组件更加清晰和可维护。
4. 在每次渲染时重复执行工作
React组件可能会在不同时间点重新渲染,如果不小心,某些工作可能会在每次渲染时都重复执行,这会降低性能。为了避免这种情况,可以使用useMemo和useCallback来记忆化操作,以便它们不会在每次渲染时重新计算。以下是一个示例:
function List({ items }) {
// 不使用useMemo - 每次渲染都会重新过滤
const filteredItems = items.filter(item => item.active);
// 使用useMemo - 只在items发生变化时重新过滤
const filteredItems = useMemo(() => items.filter(item => item.active), [items]);
}
通过使用useMemo,可以避免在每次渲染时重新计算filteredItems,从而提高性能。
5. 不正确使用useEffect钩子
useEffect钩子用于处理副作用,但如果不正确使用它,可能会导致创建多个事件监听器,这会引发问题。正确使用useEffect的方法包括将清理函数返回以取消订阅,以及使用空的依赖数组以确保只运行一次。以下是一个示例:
// 不良示例 - 每次渲染都会创建新的事件监听器
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
});
// 良好示例 - 只在组件挂载时创建事件监听器
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // 空的依赖数组
通过使用空的依赖数组,确保了事件监听器只在组件挂载时创建一次。
6. 不正确使用布尔运算符
在React组件中,经常需要根据条件来渲染不同的内容。然而,不正确使用布尔运算符可能会导致意外的问题。例如:
// 不良示例 - 使用 && 运算符
function ShoppingCart({ items }) {
return (
<div>
{items.length && <p>Items in cart: {items.length}</p>}
</div>
);
}
在上述示例中,当items.length为0时,<p>元素将不会渲染,这可能不是我们期望的结果。为了避免这种情况,最好将条件转化为布尔值,如下所示:
// 良好示例 - 使用Boolean()将条件转换为布尔值
function ShoppingCart({ items }) {
return (
<div>
{Boolean(items.length) && <p>Items in cart: {items.length}</p>}
</div>
);
}
通过将条件转换为布尔值,我们可以确保<p>元素按预期渲染。
7. 到处使用三元表达式进行条件渲染
三元表达式是一种强大的条件渲染工具,但滥用它可能会导致代码难以阅读。特别是当多个三元表达式嵌套在一起时,代码会变得混乱。考虑以下示例:
// 不良示例 - 多个嵌套的三元表达式
function UserProfile({ user, isAdmin, isOwner }) {
return (
<div>
{isAdmin ? (
<p>Admin</p>
) : isOwner ? (
<p>Owner</p>
) : (
<p>User</p>
)}
</div>
);
}
在上述示例中,多个三元表达式嵌套在一起,使代码难以理解。为了提高可读性,可以考虑使用函数或组件来代替三元表达式。以下是一个改进的示例:
// 良好示例 - 使用函数代替三元表达式
function UserProfile({ user, isAdmin, isOwner }) {
function getUserRole() {
if (isAdmin) {
return 'Admin';
} else if (isOwner) {
return 'Owner';
} else {
return 'User';
}
}
return (
<div>
<p>{getUserRole()}</p>
</div>
);
}
通过使用函数,我们使代码更易读和维护。
8. 不定义属性类型或不解构属性
为组件的属性定义类型和解构属性是一种良好的实践,它有助于提高代码的可维护性和稳定性。在日常工作中,我们应该使用PropTypes或TypeScript等工具来为属性添加类型定义,并解构属性以使其更清晰。以下是一个示例:
// 不良示例 - 未定义属性类型和未解构属性
function Person(props) {
return (
<div>
<p>Name: {props.name}</p>
<p>Age: {props.age}</p>
</div>
);
}
// 良好示例 - 定义属性类型和解构属性
import PropTypes from 'prop-types';
function Person({ name, age }) {
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
}
Person.propTypes = {
name: PropTypes.string,
age: PropTypes.number,
};
通过定义属性类型和解构属性,可以提高代码的可读性,并在属性类型错误时获得警告。
9. 较大的应用程序没进行代码拆分
对于大型React应用程序,应该考虑使用代码拆分(Code Splitting)以提高初始加载性能。代码拆分允许将代码分割为较小的块,这些块可以在需要时加载,从而减小初始包的大小。以下是一个示例:
import Loadable from 'react-loadable';
const AsyncComponent = Loadable({
loader: () => import('./AsyncComponent'),
loading: () => <div>Loading...</div>,
});
function App() {
return (
<div>
<AsyncComponent />
</div>
);
}
通过使用代码拆分,可以提高应用程序的加载速度,特别是对于较大的应用程序。
结论
在React开发中,避免这九个不良习惯可以提高代码质量、性能和可维护性。通过使用示例代码来说明这些问题以及如何避免它们,可以帮助我们在日常工作中编写更高质量的React应用程序。
日常工作中需要避免的9个React坏习惯的更多相关文章
- Shell在日常工作中的应用实践
作者:京东物流 李光新 1 Shell可以帮我们做什么 作为一名测试开发工程师,在与linux服务器交互过程中,大都遇到过以下这些问题: •一次申请多台服务器,多台服务器需要安装相同软件,配置相同的环 ...
- 关于git你日常工作中会用到的一些东西
前言 git是一个版本控制工具, 版本控制主要的好处有三点: 从当前版本回退到任意版本 查看历史版本 对比两个版本差异 git 相关术语 repository 仓库 branch 分支 summary ...
- 博主日常工作中使用的shell脚本分享
前言: 今天给大家分享一篇在我工作中常用的一个shell脚本,里面有一些我们常用到的shell操作.该脚本用于本地电脑和服务器交互上,实现以下功能: 自动拉取自己个人电脑上的源码到服务器上yocto包 ...
- Git 日常工作中使用的命令记录
前言 这篇文章主要是介绍我在使用Git中的有一些忘记了,但是很重要的命令. 20190424 Git 历史信息 username 和 email 更改 git config alias.chang ...
- 日常工作中VBA代码积累
1.超链接地址提取 Function GetURL(rng As Range) As String On Error Resume Next GetURL = rng.Hyperlinks(1).Ad ...
- 日常工作中的点滴:C# 根据字节长度截包含中文的字符串
方法中利用正则表达式判断某个字符是否是中文 public string SubStringB(string text,int length){ int target=0; int b=0; for(i ...
- 日常工作中的点滴总结from 2014-03
一 关于 写方案: 写某个产品的方案基本应包括以下几点: 1产品目前现状(国内外) 2产品意义.作用 3产品架构 4产品优势 5产品功能讲解 二 关于 处理下属工作方向不正确的事务 首先 先肯定 下 ...
- 日常工作中使用的一些Mongodb语句
.通过_userID字段查询重复录入内容 > db.template.aggregate({}}},{$}}) .查询 db.template.find({"group_7ee1247 ...
- 程序猿的日常——工作中常用的Shell脚本
工作当中总是会有很多常用的linux或者命令,这里就做一个总结 文件远程拷贝 如果想把文件从本机拷贝到远程,或者从远程下载文件到本地. # 把本地的jar拷贝到远程机器xxxip的/home/sour ...
- 日常工作中常见的mysql优化技巧
1.介绍一下MYSQL经常使用的优化技巧. MySQL 自带 slow log 的分析工具 mysqldumpslow ,可是没有说明.本文通过分析该脚本,介绍了其用法. slow log 是 MyS ...
随机推荐
- 4G EPS 中的各种唯一标识
目录 文章目录 目录 电信运营商的唯一标识:PLMN.MCC 与 MNC 移动用户的唯一标识:IMSI.MSIN 与 MSISDN/MDN 移动用户的唯一临时标识:TMSI.GUTI 与 GUMMEI ...
- pyqt5 子线程如何操作主线程GUI
一.简介 在使用pyqt5编写gui时遇到两个问题,会导致界面崩溃,今天就围绕这两个问题来简单说明和改进. 1.在主线程中使用while无限循环会导致界面崩溃 2.在子线程中操作主线程gui会导致界面 ...
- .NET 中的表达式树
.NET 中的表达式树(Expression Trees) 表达式树是什么? 表达式树(Expression Trees)是.NET框架中的一个强大功能,它将代码表示为一个由表达式节点组成的树形结构. ...
- 大数据之Hadoop集群中Yarn常用命令
Yarn状态的查询,除了可以在hadoop103:8088页面查看以外,还可以通过命令操作.常见的命令操作如下所示. 需求:执行WordCount案例,并通过Yarn命令查看任务运行情况.原文:sw- ...
- MQTT 实践总结
QMQX 文档:https://www.emqx.io/docs/zh/latest/ MQTT 入门:https://www.emqx.com/zh/mqtt-guide 通过案例理解 MQTT 主 ...
- HTML——文件上传域
文件上传是网站中一种常见的功能.例如百度网盘.QQ 邮箱以及有道云笔记都可以实现文件的上传.在 HTML 中,把 <input> 标签的 type 属性设置为 file 就可以实现上传文件 ...
- Servlet中/和/*的区别详解
Servlet中/和/*的区别详解 问题 在搭建springmvc项目时,DispatcherServlet配置为/*时welcome-file-list失效了报404异常, 配置为/时可以正常访问, ...
- 莫烦tensorflow学习记录 (5)什么是过拟合 (Overfitting)
什么是过拟合 (Overfitting) 莫烦讲的非常通俗易懂可以看看https://mofanpy.com/tutorials/machine-learning/tensorflow/intro-o ...
- nginx37条优化
nginx优化: 1. cpu:核心配置 方法1: worker_processes auto; 自动调用[推荐] 方法2: worker_processes 4; 手工配置 检查CPU核心:yum ...
- css做多列瀑布流
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...