Angular NGXS 不会重新计算选择器,除非所选数据的状态已更新
Angular NGXS don't recalculate selectors unless the selected data is updated in state
我的 NGXS 状态定义如下
export interface Project{
_id:string,
name:string
}
export class ProjectStateModel {
projects: Project[];
}
@State<ProjectStateModel>({
name: 'Projects',
defaults: {
projects: [{_id:'111', name:'Project 1'}, {_id:'222', name: 'Project 2'}]
}
})
@Selector()
static getAll(state: ProjectStateModel) {
return state.projects;
}
@Selector()
static getById(state: ProjectStateModel) {
return (id) => {
return state.projects.find(p => p._id === id);
};
}
@Action(ProjectsAction.Add)
add({ getState, patchState }: StateContext<ProjectStateModel>, { payload }: ProjectsAction.Add)
{
const state = getState();
patchState({
projects: [...state.projects, ...payload]
})
}
这是一个非常直接的状态实现。国家默认有2个项目; 2 个选择器,一个用于获取所有项目,另一个用于通过 ID 和一个添加新项目的操作。
我正在使用其中一个组件中的状态,如下所示
export class ProjectDetailComponent{
selectedPROJ: Project;
selectedPROJ$: Observable<Project>;
constructor(){
this.selectedPROJ$ = this.store.select(ProjectState.getById)
.pipe(map(filterFn => filterFn('111')));
this.test = this.selectedPROJ$.subscribe(p => {
console.log(p); //this get logged every time there is a change in state even though the project 111 hasn't changed
})
}
}
我面临的问题是每次我更新状态(比如向状态添加新项目)时,即使从状态中选择的项目没有改变,通过 id 获取的选择器也会重新触发。
例如,在上面显示的代码中,我选择了 ID 为 111
的项目。如果我发送 Add
操作来添加新项目,选择器 getById
会重新触发。
在 NGSX 中有没有什么方法可以定义一个参数化的选择器,只有当所选项目的状态发生变化时才会被触发?
我看过 NGXS 文档中的 injectContainerState
,但不明白如何将其与此参数化选择器一起使用。
选择器将根据其选择器被记忆。
@Selector() // <-- no selector injected
static getById(state: ProjectStateModel)
由于上面的选择器没有任何对状态标记、状态 class 或其他选择器的引用,因此默认情况下,每次状态更改时选择器都会 运行。选择器的强大之处在于您可以在它们的基础上创建细粒度的选择器。
另一种选择是使用动态选择器。基本上在需要时创建选择器并传入所需的参数。这是一个例子:
https://stackblitz.com/edit/ngxs-selectors-upgky4?file=src/app/app.component.ts
该示例没有展示最佳做法,而且非常粗糙。例如,您不能更改 ID。但它确实向您展示了另一种实现您想要的方法。
我的 NGXS 状态定义如下
export interface Project{
_id:string,
name:string
}
export class ProjectStateModel {
projects: Project[];
}
@State<ProjectStateModel>({
name: 'Projects',
defaults: {
projects: [{_id:'111', name:'Project 1'}, {_id:'222', name: 'Project 2'}]
}
})
@Selector()
static getAll(state: ProjectStateModel) {
return state.projects;
}
@Selector()
static getById(state: ProjectStateModel) {
return (id) => {
return state.projects.find(p => p._id === id);
};
}
@Action(ProjectsAction.Add)
add({ getState, patchState }: StateContext<ProjectStateModel>, { payload }: ProjectsAction.Add)
{
const state = getState();
patchState({
projects: [...state.projects, ...payload]
})
}
这是一个非常直接的状态实现。国家默认有2个项目; 2 个选择器,一个用于获取所有项目,另一个用于通过 ID 和一个添加新项目的操作。
我正在使用其中一个组件中的状态,如下所示
export class ProjectDetailComponent{
selectedPROJ: Project;
selectedPROJ$: Observable<Project>;
constructor(){
this.selectedPROJ$ = this.store.select(ProjectState.getById)
.pipe(map(filterFn => filterFn('111')));
this.test = this.selectedPROJ$.subscribe(p => {
console.log(p); //this get logged every time there is a change in state even though the project 111 hasn't changed
})
}
}
我面临的问题是每次我更新状态(比如向状态添加新项目)时,即使从状态中选择的项目没有改变,通过 id 获取的选择器也会重新触发。
例如,在上面显示的代码中,我选择了 ID 为 111
的项目。如果我发送 Add
操作来添加新项目,选择器 getById
会重新触发。
在 NGSX 中有没有什么方法可以定义一个参数化的选择器,只有当所选项目的状态发生变化时才会被触发?
我看过 NGXS 文档中的 injectContainerState
,但不明白如何将其与此参数化选择器一起使用。
选择器将根据其选择器被记忆。
@Selector() // <-- no selector injected
static getById(state: ProjectStateModel)
由于上面的选择器没有任何对状态标记、状态 class 或其他选择器的引用,因此默认情况下,每次状态更改时选择器都会 运行。选择器的强大之处在于您可以在它们的基础上创建细粒度的选择器。
另一种选择是使用动态选择器。基本上在需要时创建选择器并传入所需的参数。这是一个例子:
https://stackblitz.com/edit/ngxs-selectors-upgky4?file=src/app/app.component.ts
该示例没有展示最佳做法,而且非常粗糙。例如,您不能更改 ID。但它确实向您展示了另一种实现您想要的方法。