首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 课程介绍
02 | React出现的历史背景及特性介绍
03 | 以组件方式考虑UI的构建
04 | JSX的本质 : 不是模板引擎,而是语法糖
05 | React组件的生命周期及其使用场景
06 | 理解Virtual DOM及key属性的作用
07 | 组件设计模式 : 高阶组件和函数作为子组件
08 | 理解新的Context API及其使用场景
09 | 使用脚手架工具创建React项目
10 | 打包和部署
11 | Redux(1) : 前端为何需要状态管理库
12 | Redux(2) : 深入理解Store、Action、Reducer
13 | Redux(3) : 在React中使用Redux
14 | Redux(4) : 理解异步Action、Redux中间件
15 | Redux(5) : 如何组织Action和Reducer
16 | Redux(6) : 理解不可变数据(Immutability)
17 | React Router(1):路由不只是页面切换,更是代码组织方式
18 | React Router(2):参数定义,嵌套路由的使用场景
19 | UI组件库对比和介绍:Ant.Design、Material UI、Semantic UI
20 | 使用Next.js创建React同构应用
21 | 使用Jest、Enzyme等工具进行单元测试
22 | 常用开发调试工具:ESLint、Prettier、React DevTool、Redux DevTool
23 | 前端项目的理想架构:可维护、可扩展、可测试、易开发、易建构
24 | 拆分复杂度(1):按领域模型(feature)组织代码,降低耦合度
25 | 拆分复杂度(2):如何组织component、action和reducer
26 | 拆分复杂度(3):如何组织React Router的路由配置
27 | 使用Rekit(1):创建项目,代码生成和重构
28 | 使用Rekit(2):遵循最佳实践,保持代码一致性
29 | 使用React Router管理登录和授权
30 | 实现表单(1):初始数据,提交和跳转
31 | 实现表单(2):错误处理,动态表单元素,内容动态加载
32 | 列表页(1):搜索,数据缓存和分页
33 | 列表页(2):缓存更新,加载状态,错误处理
34 | 页面数据需要来源多个请求的处理
35 | 内容页的加载与缓存
36 | 基于React Router实现分步操作
37 | 常见页面布局的实现
38 | 使用React Portals实现对话框,使用antd对话框
39 | 集成第三方JS库:以d3.js为例
40 | 基于路由实现菜单导航
41 | React中拖放的实现
42 | 性能永远是第一需求:时刻考虑性能问题
43 | 网络性能优化:自动化按需加载
44 | 使用Reselect避免重复计算
45 | 下一代React:异步渲染
46 | 使用Chrome DevTool进行性能调优&结课测试
当前位置:
首页>>
技术小册>>
深入学习React实战进阶
小册名称:深入学习React实战进阶
### 44 | 使用Reselect避免重复计算 在React应用开发中,随着应用复杂度的增加,组件间的数据依赖和状态管理变得尤为关键。当多个组件依赖于同一数据源或经过复杂计算得出的状态时,如何高效且优雅地管理这些状态成为了一个挑战。此时,`reselect`库凭借其强大的功能——通过创建可记忆(memoizable)的选择器(selectors),帮助开发者避免不必要的重复计算,优化应用性能,成为React生态中不可或缺的一部分。 #### 引言:重复计算的代价 在React中,组件的重新渲染是性能优化的重要关注点。如果组件的`props`或`state`发生变化,React会触发组件的重新渲染流程。然而,当这些变化并不直接影响组件的展示或行为时,这种重新渲染就是不必要的。特别是当数据来源于复杂计算或跨多个组件共享时,重复的计算过程会极大地影响应用的性能。 #### Reselect简介 `reselect`是一个JavaScript库,专为React和Redux(或其他可预测状态管理库)设计,用于创建可记忆的选择器。选择器本质上是一个函数,它接收当前的状态(或一组输入)并返回一个新的值。通过使用`reselect`,开发者可以定义这些选择器,以便在输入不变时,自动重用上一次的计算结果,从而避免不必要的计算开销。 #### 为什么选择Reselect 1. **性能优化**:通过缓存计算结果,`reselect`能够显著减少CPU使用率,特别是在处理大量数据或复杂计算时。 2. **可预测性**:选择器提供了清晰的数据依赖关系,使得数据流向更加透明,易于理解和调试。 3. **灵活性**:`reselect`的选择器可以组合使用,形成更复杂的数据转换管道,同时保持高效的缓存策略。 4. **简洁性**:减少组件中的逻辑代码,使组件更加专注于UI的渲染,提升代码的可维护性。 #### Reselect的基本使用 ##### 安装Reselect 首先,你需要安装`reselect`库。在你的项目目录下,运行以下npm或yarn命令: ```bash npm install reselect # 或者 yarn add reselect ``` ##### 创建一个简单的选择器 ```javascript import { createSelector } from 'reselect'; // 假设我们有一个全局状态对象,包含多个字段 const state = { users: [ { id: 1, name: 'Alice', age: 25 }, { id: 2, name: 'Bob', age: 30 }, // ... ], activeUserId: 1 }; // 创建一个选择器来获取当前活跃用户的名字 const selectActiveUserId = state => state.activeUserId; const selectUsers = state => state.users; const selectActiveUserName = createSelector( [selectActiveUserId, selectUsers], (activeUserId, users) => users.find(user => user.id === activeUserId)?.name ); // 使用selectActiveUserName选择器 console.log(selectActiveUserName(state)); // 输出: Alice ``` 在这个例子中,`createSelector`接收一个数组作为第一个参数,数组中的每个元素都是一个选择器函数,它们分别返回计算所需的不同部分数据。第二个参数是一个函数,它接收这些选择器函数返回的结果作为参数,并返回最终的计算结果。如果任何输入选择器的返回值没有变化,那么`createSelector`会返回上一次计算的结果,避免重新执行计算逻辑。 #### 进阶使用:组合选择器 `reselect`的强大之处不仅在于它可以避免重复计算,更在于它能够支持选择器的组合。通过组合不同的选择器,你可以构建出更加复杂但高效的数据处理流程。 ```javascript // 假设我们还需要一个选择器来根据用户年龄筛选用户 const selectUsersOlderThan = age => createSelector( [selectUsers], users => users.filter(user => user.age > age) ); // 现在,我们可以组合selectActiveUserId和selectUsersOlderThan来找到比当前活跃用户年龄大的所有用户 const selectUsersOlderThanActive = createSelector( [selectActiveUserId, selectUsers], (activeUserId, users) => { const activeUserAge = users.find(user => user.id === activeUserId)?.age || 0; return selectUsersOlderThan(activeUserAge)({ users }); } ); // 注意:这里的selectUsersOlderThan需要稍作修改以支持传入当前年龄 // 修改后的selectUsersOlderThan可能看起来像这样(为了简洁,这里不展开完整代码) // 使用selectUsersOlderThanActive选择器 console.log(selectUsersOlderThanActive(state)); // 输出: 所有比Alice年龄大的用户列表 ``` 注意,在上述例子中,我们遇到了一个常见的挑战:如何在组合选择器时处理异步或依赖其他选择器的结果。虽然`reselect`本身不支持直接处理异步操作,但你可以通过其他方式(如使用Redux中间件如`redux-thunk`或`redux-saga`)来处理异步逻辑,并在选择器中使用这些异步操作的结果。 #### 注意事项 - **确保输入选择器是纯净的**:为了有效利用缓存,传递给`createSelector`的选择器函数必须是无副作用的,即给定相同的输入总是返回相同的输出。 - **谨慎处理复杂数据结构**:对于深层嵌套或频繁变化的数据结构,可能需要更精细的缓存策略,或者考虑使用其他状态管理方案。 - **注意选择器的生命周期**:在组件卸载时,如果选择器依赖于外部资源(如API调用结果),确保妥善处理这些资源的清理工作,避免内存泄漏。 #### 结论 `reselect`作为React和Redux生态中的一个重要工具,通过提供可记忆的选择器,极大地帮助开发者优化应用性能,减少不必要的计算开销。通过合理使用`reselect`,你可以构建出更加高效、可维护的React应用。无论是在处理大量数据、复杂计算,还是优化组件性能方面,`reselect`都是你的得力助手。希望本章节的内容能帮助你深入理解并高效应用`reselect`,从而在React实战进阶的道路上更进一步。
上一篇:
43 | 网络性能优化:自动化按需加载
下一篇:
45 | 下一代React:异步渲染
该分类下的相关小册推荐:
剑指Reactjs
React全家桶--前端开发与实例(上)
React 进阶实践指南
ReactJS面试指南
React全家桶--前端开发与实例(下)