关于createSelector外部选择器未使用输入及参数配置的技术咨询
1. 为何要在createSelector的外部选择器中添加未被使用的输入选择器?
createSelector的核心逻辑是基于所有输入选择器的返回值变化来缓存计算结果。如果你的最终计算逻辑依赖某个状态(比如items),但没把对应的状态选择器放进外部输入列表,那当这个状态更新时,createSelector会因为输入列表里没有这个依赖,误以为结果不需要更新,直接返回旧的缓存值。
举个实际场景:你要做一个筛选分类商品的选择器,最终逻辑是用items和categoryName筛选,但如果外部选择器只传了获取categoryName的函数,没传items的选择器,那items新增或修改后,选择器不会重新计算,页面会一直显示旧数据。所以哪怕某个输入选择器在参数层没直接用,只要最终计算依赖它,就必须放进外部列表,保证缓存失效逻辑正确。
2. 带额外参数的选择器中,为何要把对应状态(如items)和参数选择器放在一起?
createSelector的输入列表规则是:状态选择器(从Redux取数)在前,接收组件参数的选择器在后,而且所有输入选择器都会接收到组件调用时传入的state和额外参数。
当你需要基于items状态和组件传的categoryName计算结果时,把items放进输入列表有两个关键作用:
- 让createSelector追踪
items的变化,一旦items更新,就触发重新计算 - 保证参数选择器能正确拿到组件传的参数:参数选择器的第一个参数是Redux的
state,第二个及以后才是组件传的额外参数,有了前面的状态选择器,整个参数传递逻辑才会对齐。
如果不把items放进输入列表,不仅缓存逻辑会失效,参数选择器也没法正确获取组件传的值。
3. 关于参数选择器的两个疑问
为什么(_, categoryName) => categoryName能正常工作?
这里的_就是个占位符。因为参数选择器的第一个参数固定是Redux的整个state对象,但我们这里不需要用到state,所以用_来占位置,这样第二个参数categoryName才能准确对应到组件调用选择器时传入的额外参数。要是不写这个占位符,categoryName会被当成state来接收,自然拿不到正确的分类名。
为什么[items, (categoryName) => categoryName]无法正常工作?
这个写法的问题出在参数匹配上:当输入列表里有items(状态选择器),后面的函数会接收到state和组件传的额外参数——也就是这个函数的第一个参数是state,第二个才是categoryName。但你只写了(categoryName)这一个参数,那这个参数实际拿到的是Redux的state,而不是组件传的分类名,逻辑自然就错了,没法正常筛选数据。
正确的写法应该是(state, categoryName) => categoryName(或者用_代替state),这样才能正确拿到组件传的参数。
内容的提问来源于stack exchange,提问作者Victor Hugo

