首页 > 解决方案 > React + TypeScript - 如何使用“动态”更改集更新单个对象的状态

问题描述

我想在条件更新列表的末尾更新状态并累积要立即提交的更改(以避免 setState 出现异步问题)。

interface IMyComponentState {
    a: string;
    b: string;
    c: string;
}

(...)

updateState = (condition1: boolean, condition2: boolean) => {
    const stateChanges: Partial<IMyComponentState> = {};

    if (condition1) {
        stateChanges.a = 'someValue 1';
    }
    if (condition2) {
        stateChanges.b = 'someValue 2';
    }
    this.setState(
        { ...this.state, ...stateChanges },
        () => this.doSomethingThatDependsOnState()
    );
}

这很好用,但是有没有办法在不使用的情况下做到这一点this.state,如下所示?

    this.setState(
        {...stateChanges},
        (...)
    );

这里tslint抱怨setState需要一个类型的对象,Pick<IMyComponentState, "a" | "b" | "c">但这需要我提前指定(并预测)要更改的属性,这是不可能的。我听说 React 的 diffing 算法会检查引用,但我仍然担心将整个state对象放入setState会增加额外的开销或者是不必要的。

标签: reactjstypescriptsetstatetslint

解决方案


首先,你不需要传播this.state,React 只会将状态更改应用到指定的键。

其次,setState故意不使用的类型Partial<T>,这是因为显式undefined设置键会执行状态更新,所以它使用(GitHub问题在这里讨论更多Pick

要解决此问题,您可以将 state update 转换为Pick<IMyComponentState, keyof IMyComponentState>;

updateState = (condition1: boolean, condition2: boolean) => {
  const stateChanges = {};

  if (condition1) {
    stateChanges.a = 'someValue 1';
  }
  if (condition2) {
    stateChanges.b = 'someValue 2';
  }
  this.setState(
    { ...stateChanges } as Pick<IMyComponentState, keyof IMyComponentState>,
    () => this.doSomethingThatDependsOnState()
  );
}

推荐阅读