Подтвердить что ты не робот

Разрешить компилятору typescript вызвать setState только для одного свойства состояния реакции

Я использую Typescript с React для проекта. Основной компонент получает переданное состояние с этим интерфейсом.

interface MainState {
  todos: Todo[];
  hungry: Boolean;
  editorState: EditorState;  //this is from Facebook draft js
}

Однако код ниже (только выдержка) не будет компилироваться.

class Main extends React.Component<MainProps, MainState> {
  constructor(props) {
    super(props);
    this.state = { todos: [], hungry: true, editorState: EditorState.createEmpty() };
  }
  onChange(editorState: EditorState) {
    this.setState({
      editorState: editorState
    });
  }
}

Компилятор жалуется, что в методе onChange, где я только пытаюсь установить свойствоState для одного свойства, свойство todos и свойство hungry отсутствуют в типе { editorState: EditorState;}. Другими словами, мне нужно установить состояние всех трех свойств в функции onChange, чтобы скомпилировать код. Для его компиляции мне нужно сделать

onChange(editorState: EditorState){
  this.setState({
    todos: [],
    hungry: false,
    editorState: editorState
  });
}

но нет причин устанавливать свойства todos и hungry в этой точке кода. Каков правильный способ вызова setState только для одного свойства в typescript/реагировать?

4b9b3361

Ответ 1

Изменить

Обновлены определения для реакции и подпись для setState:

setState<K extends keyof S>(state: Pick<S, K>, callback?: () => any): void;

Где Pick<S, K> - это встроенный тип, который был добавлен в Typescript 2.1:

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
}

Для получения дополнительной информации см. Mapped Types.
Если у вас все еще есть эта ошибка, вы можете захотеть обновить свои аналитические определения.

Оригинальный ответ:

Я сталкиваюсь с тем же.

Двумя способами, с которыми мне удается справиться с этой досадной проблемой, являются следующие:

(1) литье/утверждение:

this.setState({
    editorState: editorState
} as MainState);

(2) объявление полей интерфейса как необязательное:

interface MainState {
    todos?: Todo[];
    hungry?: Boolean;
    editorState?: EditorState;
}

Если у кого-то есть лучшее решение, я был бы рад узнать!


Изменить

Пока это все еще проблема, есть два обсуждения новых функций, которые разрешат эту проблему:
Частичные типы (необязательные свойства для существующих типов)
и
Более точная набивка компонента Object.assign и React setState()

Ответ 2

Обновить состояние явно, пример с помощью счетчика

this.setState((current) => ({ ...current, counter: current.counter + 1 }))

Ответ 3

Изменить: НЕ ИСПОЛЬЗУЙТЕ это решение, предпочитайте fooobar.com/questions/152544/... Подробнее см. Комментарии.

Теперь, когда оператор распространения отправлен в TS, мое предпочтительное решение

this.setState({...this.state, editorState}); // do not use 1!

Ответ 4

Я думаю, что лучший способ сделать это - использовать Partial

Объявите свой компонент следующим образом.

class Main extends React.Component<MainProps, Partial<MainState>> {
}

Частично автоматически изменяет все ключи на необязательные.