reselect 的推荐用法是将参数作为第二个参数传入 createselector,而非用闭包返回新 selector;后者每次渲染都会创建全新 selector 实例,导致缓存失效、重复计算,带来显著性能损耗。
在使用 Reselect 构建 Redux 状态选择器时,正确利用其 memoization 机制对应用性能至关重要。官方推荐的参数化 selector 写法如下:
const selectOrdersByCustomer = createSelector( state => state.orders, (state, customerId) => customerId, (orders, customerId) => orders.filter(order => order.customerId === customerId) ); // 在组件中调用: const orders = useSelector(state => selectOrdersByCustomer(state, customerId));
该模式下,selectOrdersByCustomer 是单个共享的 memoized selector 实例,其内部缓存(基于输入组合的 recomputations 和 lastResult)可跨多次调用复用。只要 state.orders 和 customerId 均未变化,输出函数(filter)将完全跳过执行。
而闭包式写法看似简洁,实则违背了 Reselect 的设计前提:
const selectOrdersByCustomer = customerId =>
createSelector(
state => state.orders,
orders => orders.filter(order => order.customerId === customerId)
);
// ❌ 错误用法:每次调用都新建 selector
const orders = useSelector(selectOrdersByCustomer(customerId));问题在于:selectOrdersByCustomer(customerId) 每次执行都会返回一个全新的 selector 函数。即使 customerId 相同,每个 selector 都拥有独立的缓存空间,且因组件重渲染频繁触发(如 props 变化、父组件更新),导致:
✅ 正确实践要点:
总结:闭包式 selector 看似灵活,实则是典型的「伪优化」——牺牲 Reselect 的核心优势(结构共享 + 引用缓存)换取代码表层简洁。在中大型应用中,这类写法会快速演变为性能瓶颈。坚持官方推荐模式,才能真正发挥 Reselect 的 memoization 效能。