如何防止Angular商店分派创建无限循环

时间:2020-11-12 08:47:22

标签: angular typescript redux ngxs

我最近遇到一个问题,并写了一个简化版本。我想知道最好的方法是解决这样的问题。假设您有一个带有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;
  }
}

现在这将在状态更新时创建一个无限循环,并且组件不断接收更新后的状态值,但是如何防止这种情况发生呢?如果我真的需要组件使用选择器的输入来调用函数,但该函数还需要更改相同的状态怎么办?

1 个答案:

答案 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));
  }
}