求助:NGXS中无关联状态为何会触发@Selector()选择器?
看起来你遇到的问题核心在于Ngxs配置里的injectContainerState: true选项,结合选择器的定义方式导致了非预期的触发。
为什么无关状态更新会触发你的选择器?
你在app.module.ts里配置了selectorOptions: { injectContainerState: true },这个选项的作用是让所有@Selector()装饰的选择器接收整个应用的根状态,而不是单个子状态。
也就是说,你的getIsEmptyArchive选择器里的state参数,虽然你标注了类型ChartStateModel,但实际传入的是整个应用的根状态对象。当groups.state.ts里更新groups状态时,整个根状态发生了变化,Ngxs会认为你的选择器依赖的状态(根状态)改变了,所以重新执行选择器。
而此时你访问state.isEmptyArchive时,因为根状态里并没有这个属性(它属于ChartState的切片),所以会返回undefined或者你设置的默认值,这和你观察到的“返回默认值”现象完全匹配。
如何解决?
有两种可行的方案:
方案1:关闭injectContainerState(推荐,除非你有明确需求)
如果你的应用不需要让选择器接收根状态,可以直接把这个配置项改为false(这也是Ngxs的默认值):
NgxsModule.forRoot([...stateList], { selectorOptions: { injectContainerState: false, // 修改为false suppressErrors: true } })
这样你的选择器会正常接收ChartStateModel类型的子状态,只有当ChartState本身更新时,选择器才会触发。
方案2:保留配置,修改选择器适配根状态
如果你必须开启injectContainerState,可以修改选择器,明确从根状态中提取ChartState的切片:
// 先定义根状态的类型,比如: interface AppRootState { chart: ChartStateModel; groups: GroupsStateModel; // 其他状态切片... } @Selector() static getIsEmptyArchive(rootState: AppRootState): ChartErrorTypeInterface { // 明确获取ChartState的切片 const chartState = rootState.chart; console.log(chartState.isEmptyArchive); return chartState.isEmptyArchive; }
这样Ngxs会正确追踪选择器依赖的是rootState.chart这个切片,只有当ChartState更新时才会触发选择器,其他状态的更新不会再影响它。
内容的提问来源于stack exchange,提问作者den_gera

