React + TypeScript - как обновить состояние с одним объектом с набором изменений «Dynami c» - PullRequest
0 голосов
/ 14 января 2020

Я хочу обновить состояние в конце списка условных обновлений и накапливает изменения, которые должны быть зафиксированы за один раз (чтобы избежать асинхронных c проблем с 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 проверяет ссылки, но я все еще обеспокоен тем, что помещение всего объекта state в setState приведет к дополнительным издержкам или излишне.

1 Ответ

1 голос
/ 14 января 2020

Прежде всего, вам не нужно распространять this.state, React будет применять только изменения состояния к указанным ключам.

Во-вторых, тип для setState намеренно не использует Partial<T> это потому, что установка undefined для ключа в явном виде выполнит обновление состояния, поэтому он использует Pick ( GitHub, здесь обсуждается подробнее )

Чтобы обойти эту проблему, вы можете привести свое обновление состояния к 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()
  );
}
...