angular - 如何防止 Angular 商店调度创建无限循环
问题描述
我最近遇到一个问题,并写了一个简化版本。我想知道解决此类问题的最佳方法是什么。假设您有一个简单的状态,其中包含一个 updateState 操作和一个选择器,它从状态中选择该值,如下所示
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;
}
}
现在这将创建一个无限循环,因为状态更新并且组件不断接收更新的状态值,但是您将如何防止这种情况发生呢?如果我真的需要组件使用来自选择器的输入调用函数,但该函数也需要更改相同的状态怎么办?
解决方案
您可以将选择器的输出用作操作输入,不用担心。我知道这是一个人为的 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));
}
}
推荐阅读
- reactjs - 我们可以像在 MS Teams 中一样在机器人模拟器中渲染反应自适应卡吗
- java - 如何在 Swagger 中注释对象响应数组
- mongodb - 从数组聚合中删除元素
- java - ANTL4 语法编译 Nullpointer 异常
- ios - 在一台设备上绘图以在另一台设备上可见
- java - 如何使用 Spring Data ReactiveElasticsearch 进行源过滤?
- javascript - 为什么A按钮有效而B无效?
- google-bigquery - LEFT JOIN 丢弃结果中的左行?
- javascript - Angular Pagination:显示一组 A4 大小的页面
- ionic-framework - 当我尝试使用 adnroid studio 构建项目时,清单合并失败