
使用闭包动态创建 reselect selector(如 `selectbycustomer(id)`)会导致每次渲染都新建一个独立的 memoized 函数,无法复用缓存,造成重复计算和内存浪费;而标准的参数化 selector(接受 `(state, props)`)共享同一实例,真正实现高效 memoization。
在 React + Redux 应用中,Reselect 是优化派生状态计算的关键工具。但 selector 的写法直接影响性能表现。两种常见模式看似等价,实则存在本质差异:
✅ 推荐方式:参数化 selector(单实例 + 多参数)
const selectOrdersByCustomer = createSelector( state => state.orders, (state, customerId) => customerId, // 第二个输入选择器接收 props 参数 (orders, customerId) => orders.filter(order => order.customerId === customerId) ); // 在组件中使用: const orders = useSelector(state => selectOrdersByCustomer(state, customerId));
该方式仅创建一个 selector 实例,其内部缓存(recomputations()、lastResult() 等)全程复用。只要 state.orders 和 customerId 均未变化,输出选择器(output selector)完全跳过执行,直接返回缓存结果。
❌ 危险方式:闭包式 selector 工厂(每次渲染新建实例)
const selectOrdersByCustomer = customerId =>
createSelector(
state => state.orders,
orders => orders.filter(order => order.customerId === customerId)
);
// 在组件中使用(⚠️ 错误!):
const orders = useSelector(selectOrdersByCustomer(customerId)); // 每次渲染都调用 factory!此处 selectOrdersByCustomer(customerId) 每次组件渲染都会返回一个全新的 selector 函数。即使 customerId 相同,每个 selector 都拥有独立的缓存空间,且无任何共享机制。结果是:
- 输出选择器被反复执行(如示例中 console.count 触发 3 次);
- 缓存失效,=== 比较返回 false,导致不必要的对象重建;
- 内存中堆积大量冗余 selector 实例,增加 GC 压力。
? 关键验证:recomputations() 与引用相等性
通过日志可清晰验证差异:
- 参数化 selector:recomputations() 返回 1,三次调用结果严格 ===;
- 闭包 selector:三次调用触发三次 console.count,且 s1 === s2 为 false —— 每次都生成新数组。
? 正确使用闭包的场景(极少数)
若确需工厂模式(如动态配置 selector),必须确保 selector 实例稳定复用,例如:
// ✅ 正确:useMemo 缓存 selector 实例
const selectByCustomer = useMemo(
() => createSelector(
state => state.orders,
orders => orders.filter(o => o.customerId === customerId)
),
[customerId] // 依赖变更时才重建 selector
);
const orders = useSelector(selectByCustomer);但即便如此,仍不如原生参数化 selector 简洁、可靠、符合 Reselect 设计哲学。
? 总结建议
- 优先采用 (state, props) 形式的参数化 selector,它是 Reselect 官方推荐且经过充分优化的模式;
- 避免在 useSelector 内联调用 selector 工厂函数;
- 使用 selector.recomputations() 和 selector.lastResult() 辅助调试缓存行为;
- 对高频更新的 selector,可结合 createStructuredSelector 或 defaultMemoize 的 equalityCheck 进行深度定制。
性能优化始于正确的抽象——不是“用了 memoization”,而是“用对了 memoization”。











