0

0

Reselect 中使用闭包实现带参选择器的性能陷阱与正确用法

霞舞

霞舞

发布时间:2025-12-26 11:15:08

|

600人浏览过

|

来源于php中文网

原创

Reselect 中使用闭包实现带参选择器的性能陷阱与正确用法

在 reselect 中,通过闭包(如 `customerid => createselector(...)`)创建带参数的选择器会导致每次渲染都生成新实例,使 memoization 完全失效,引发重复计算和内存浪费;而官方推荐的多参数 `createselector` 方式才能真正复用缓存。

Reselect 的核心价值在于共享、可复用、带缓存的选择器实例。其 memoization 机制依赖于两个关键前提:

  1. 选择器函数是稳定引用(即不随渲染重新创建)
  2. 输入参数能被正确捕获并参与缓存键计算

❌ 错误方式:闭包工厂模式(性能陷阱)

// 危险!每次调用 selectOrdersByCustomer(customerId) 都创建全新 selector 实例
const selectOrdersByCustomer = customerId =>
  createSelector(
    state => state.orders,
    orders => {
      console.count('⚠️ output selector executed'); // 每次渲染都触发!
      return orders.filter(order => order.customerId === customerId);
    }
  );

// 在组件中:
const orders = useSelector(selectOrdersByCustomer(customerId));

该写法看似简洁,实则违背 Reselect 设计原则:

  • selectOrdersByCustomer(customerId) 每次调用返回一个全新的 createSelector 实例
  • 每个实例拥有独立的缓存(recomputations()、memoizedResultSelector),互不共享;
  • 即使 state.orders 和 customerId 均未变化,因 selector 实例不同,缓存永远无法命中 → 输出选择器反复执行,且返回新数组(=== false)
✅ 实验验证(见原答案日志):三次调用 selectOrdersByCustomer2(1)(state) 导致输出选择器执行 3 次,且结果引用不等(false false)。

✅ 正确方式:多参数选择器(推荐标准写法)

// ✅ 稳定声明:单个 selector 实例,支持参数化输入
const selectOrdersByCustomer = createSelector(
  state => state.orders,
  (state, customerId) => customerId, // 第二个输入选择器,接收 props 参数
  (orders, customerId) => {
    console.count('✅ memoized output selector'); // 仅当 orders 或 customerId 变化时执行
    return orders.filter(order => order.customerId === customerId);
  }
);

// 在组件中(useSelector 自动透传第二个参数):
const orders = useSelector(state => selectOrdersByCustomer(state, customerId));

此方式优势显著:

Outwrite
Outwrite

AI写作浏览器插件,将您的想法变成有力的句子

下载
  • selectOrdersByCustomer 是单一、稳定的函数引用,可安全定义在模块顶层;
  • Reselect 内部将 (state, customerId) 作为缓存键(equalityCheck 默认为 ===),确保相同参数组合命中缓存;
  • 多次调用 selectOrdersByCustomer(state, 1) 仅首次执行过滤逻辑,后续直接返回缓存结果(=== true)。

⚠️ 注意事项与最佳实践

  • 避免在组件内部或 useSelector 回调中动态创建 selector(包括闭包、useMemo(() => createSelector(...)) 等);
  • 若需动态生成 selector(极少数场景),应配合 useMemo 缓存 factory 函数本身,并确保 customerId 是 useMemo 的依赖项——但通常没必要,优先用多参数模式;
  • 对于复杂参数(如对象),注意 Reselect 默认浅比较(===),必要时自定义 memoize 或 equalityCheck;
  • 使用 createSelectorCreator + lodash.memoize 可扩展缓存策略,但默认方案已满足绝大多数场景。

总结

闭包式 selector 不是“稍慢一点”,而是彻底丢失 memoization 能力——它把 Reselect 降级为普通纯函数,还额外增加了 selector 创建开销。务必坚持 Reselect 官方范式:参数通过输入选择器传入,selector 实例全局唯一、稳定复用。这是保障 React-Redux 应用高性能的关键细节之一。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

130

2025.07.29

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

26

2025.12.25

错误代码dns_probe_possible
错误代码dns_probe_possible

本专题整合了电脑无法打开网页显示错误代码dns_probe_possible解决方法,阅读专题下面的文章了解更多处理方案。

19

2025.12.25

网页undefined啥意思
网页undefined啥意思

本专题整合了undefined相关内容,阅读下面的文章了解更多详细内容。后续继续更新。

31

2025.12.25

word转换成ppt教程大全
word转换成ppt教程大全

本专题整合了word转换成ppt教程,阅读专题下面的文章了解更多详细操作。

2

2025.12.25

msvcp140.dll丢失相关教程
msvcp140.dll丢失相关教程

本专题整合了msvcp140.dll丢失相关解决方法,阅读专题下面的文章了解更多详细操作。

2

2025.12.25

笔记本电脑卡反应很慢处理方法汇总
笔记本电脑卡反应很慢处理方法汇总

本专题整合了笔记本电脑卡反应慢解决方法,阅读专题下面的文章了解更多详细内容。

5

2025.12.25

微信调黑色模式教程
微信调黑色模式教程

本专题整合了微信调黑色模式教程,阅读下面的文章了解更多详细内容。

3

2025.12.25

ps入门教程
ps入门教程

本专题整合了ps相关教程,阅读下面的文章了解更多详细内容。

4

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 0.9万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号