Разрешить компилятору 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/реагировать?
Ответы
Ответ 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>> {
}
Частично автоматически изменяет все ключи на необязательные.