reselect createSelector与memoizeOptions使用异常:自定义对比未生效
问题排查与解决
核心原因:对reselect缓存逻辑的误解 + 配置参数名错误
1. 缓存逻辑的本质误解
createSelector默认使用memoizeOne对整个选择器的输入参数进行缓存,而非输入选择器的返回值。你两次调用select(state0, 2)时,传入的state0是同一个对象引用,index都是2,所以memoizeOne判定参数未变化,直接返回缓存结果,根本不会触发输入选择器和结果函数的重新执行,因此recomputations()始终为1。
2. 配置参数名错误
你在memoizeOptions中使用的equalityCheck和resultEqualityCheck不是memoizeOne的合法参数名,正确的参数名是equalityFn,用于比较选择器的输入参数是否相同。这导致你的自定义比较逻辑完全未生效。
修复方案
方案一:修改memoizeOptions参数,强制每次调用都重新计算
将memoizeOptions中的参数名改为equalityFn,并让它始终返回false,这样无论参数是否相同,都会触发重新计算:
const select = createSelector( (state, index: number): number[] => state.a.slice(0, index), (state, index: number): string[] => state.b.slice(0, index), (a_in: number[], b_in: string[]): (number | string)[] => [...a_in, ...b_in], { memoizeOptions: { equalityFn: () => false // 强制认为参数不同,每次都重新计算 } } );
方案二:基于输入选择器的结果判断是否重新计算
如果你希望根据输入选择器的返回值(而非选择器参数)来决定是否重新计算,需要使用createSelectorCreator自定义选择器的缓存逻辑,替换默认的参数比较为输入结果比较:
import { createSelectorCreator, defaultMemoize } from "reselect"; // 自定义选择器创建器,基于输入选择器的结果进行缓存判断 const createSelectorByInputResults = createSelectorCreator( defaultMemoize, // 比较两次调用的输入选择器结果数组是否相同 (prevInputs, currInputs) => { return prevInputs.every((prev, idx) => prev === currInputs[idx]); } ); // 使用自定义创建器构建选择器 const select = createSelectorByInputResults( (state, index: number): number[] => state.a.slice(0, index), (state, index: number): string[] => state.b.slice(0, index), (a_in: number[], b_in: string[]): (number | string)[] => [...a_in, ...b_in] );
此时,因为两次调用输入选择器返回的是不同引用的数组,prev === curr会返回false,因此会触发重新计算,recomputations()会变为2。
验证结果
修改后重新运行测试,第二次调用select(state0,2)时,recomputations()的值会变为2,符合你的预期。
内容的提问来源于stack exchange,提问作者slaughter98
相关产品推荐
相关产品推荐

