我最近遇到一个问题,并写了一个简化版本。我想知道最好的方法是解决这样的问题。假设您有一个带有updateState动作的简单State和一个选择器,该选择器可以像这样从状态中选择该值
const defaults: AppStateModel = {
test: 'test'
};
@State<AppStateModel>({
name: 'app',
defaults
})
@Injectable()
export class AppState {
@Selector()
static testSelector(state: AppStateModel): string {
return state.test;
}
@Action(UpdateTest)
updateState(ctx: StateContext<AppStateModel>, { nextTest }: UpdateTest) {
ctx.patchState({
test: nextTest
});
}
}
然后我从组件中调用一个函数,该组件将选择器中的异步管道作为输入,然后像这样分派动作。
@Component({
selector: 'app-root',
template: `
<input [(ngModel)]="name">
<p>Test: {{testFunction(testSelector$ | async)}}</p>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
@Select(AppState.testSelector)
testSelector$: Observable<string>;
name: string;
constructor(private store: Store) {
}
testFunction(test: string): string {
console.log("testprint");
this.store.dispatch(new UpdateTest(this.name));
return test;
}
}
现在这将在状态更新时创建一个无限循环,并且组件不断接收更新后的状态值,但是如何防止这种情况发生呢?如果我真的需要组件使用选择器的输入来调用函数,但该函数还需要更改相同的状态怎么办?
答案 0 :(得分:1)
您可以将选择器的输出用作操作输入,请不要担心。我知道这是SO的人为例子,但是对于何时您想要分派操作以改变状态的操作还是不太清楚-如果有的话,它将被事件或其他Observable驱动在模板中将其调用,然后将在每个更改检测周期(肯定不是您想要的)上调用它。
通常,您希望触发一些输入的更改-然后通过操作来使状态发生变化。
@Component({
selector: 'app-root',
template: `
<input [ngModel]="name" (ngModelChange)="nameChanged($event)>
<p>Test: {{ testSelector$ | async }}</p>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
@Select(AppState.testSelector) testSelector$: Observable<string>;
name: string;
constructor(private store: Store) {
}
nameChanged(newName: string): void {
this.store.dispatch(new UpdateTest(newName));
}
}