[英]TypesScript wrongly assumes that property is read-only
我有一個使用打字稿創建的簡單反應組件,遇到以下奇怪的錯誤。 這是我的代碼。
interface State {
value: string
}
class App extends React.Component<{}, State> {
constructor() {
super();
this.state = {
value: ''
}
}
changeHandler = (e: any) => {
let state = Object.assign({}, this.state);
state.value = e.target.value;
this.setState(state);
}
render() {
return (
<div className="App">
<input
type="text"
value={this.state.value}
name="value"
onChange={this.changeHandler} />
</div>
);
}
}
export default App;
這就是我得到的錯誤。
錯誤TS2540:不能分配到“價值”,因為它是一個常量或只讀屬性。
這個錯誤讓我想到也許這是打字稿執行不變異狀態規則的方式。 為了驗證這一理論,我做了以下工作。
this.state.value = e.target.value
在這種情況下,我顯然可以直接改變狀態,並且可以肯定地得到相同的錯誤。
然后我想到了將界面更改為此的想法。
interface State {
value: Ivalue
}
interface Ivalue {
value: string;
}
然后,我將組件重構為使用這種新接口。
class App extends React.Component<{}, State> {
constructor() {
super();
this.state = {
value: {
value: ''
}
}
}
changeHandler = (e: any) => {
let value = Object.assign({}, this.state.value);
value.value = e.target.value;
this.setState({value});
}
render() {
return (
<div className="App">
<input
type="text"
value={this.state.value.value}
name="value"
onChange={this.changeHandler} />
</div>
);
}
}
export default App;
當然可以編譯了! 我的問題確實是2個問題。 首先,為什么打字稿不滿意我的狀態副本,就像我在使用Object.assign
第一段代碼中那樣? 第二,為什么將我的狀態對象嵌套更深一層來解決此問題?
如果Object.assign
的內部實現(或其對TypeScript的理解)是復制對象成員的描述符,而不僅僅是字段名,則它復制的是state.value
的readonly
屬性,而不僅僅是state.value
。
我不能保證這實際上發生了什么事,因為這將是我這個消息。 但這實際上是好消息,而不是壞消息。
您正在使用什么版本的事物?
另外,如果要在下一個主要版本中繼續使用setState
的功能形式, setState
養成使用它的習慣。
您可以將其重寫為:
changeHandler = (e: any) => {
this.setState({value: e.target.value});
}
或具有解構作用 :
changeHandler = ({target: {value}}: any) => {
this.setState({value});
}
在Typescript中,您可以將您的媒體資源標記為只讀。 是更好的方法,因為直接不可變狀態不是好的模式。 您必須運行setState()函數來更改狀態。
您的道具和狀態可能如下所示:
interface State {
readonly value: string;
}
我用“只讀”標記類型中的所有屬性(用於props,state,redux等)。 我想要所有的東西都是不變的:)
如果查看React組件的類型定義,可以看到state
屬性定義為Readonly<S>
,其中S
是狀態類型參數。
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L209
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.