在 reselect 中,通过闭包(如 `customerid => createselector(...)`)创建带参数的选择器会导致每次渲染都生成新实例,使 memoization 完全失效,引发重复计算和内存浪费;而官方推荐的多参数 `createselector` 方式才能真正复用缓存。
Reselect 的核心价值在于共享、可复用、带缓存的选择器实例。其 memoization 机制依赖于两个关键前提:
// 危险!每次调用 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 设计原则:
✅ 实验验证(见原答案日志):三次调用 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));此方式优势显著:
闭包式 selector 不是“稍慢一点”,而是彻底丢失 memoization 能力——它把 Reselect 降级为普通纯函数,还额外增加了 selector 创建开销。务必坚持 Reselect 官方范式:参数通过输入选择器传入,selector 实例全局唯一、稳定复用。这是保障 React-Redux 应用高性能的关键细节之一。