React + TypeScript - 如何使用 "dynamic" 组更改更新单个对象的状态

React + TypeScript - how to update state with single object with a "dynamic" set of changes

我想在条件更新列表的末尾更新状态并累积要立即提交的更改(以避免 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 中会增加额外的开销或者是不必要的。

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

其次,setState 的类型有意不使用 Partial<T>,这是因为在键 上显式设置 undefined 将执行状态更新,因此它使用 Pick (GitHub issue here talking more about it)

要解决此问题,您可以将状态更新强制转换为 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()
  );
}