无法分配给'state',因为它是常量或只读属性

jea*_*luc 39 types typescript reactjs

当我在这个问题上进行搜索时,我只能找到this.state直接在方法体中某处修改而不是使用的问题this.setState().我的问题是我想在构造函数中设置一个起始状态,如下所示:

export default class Square extends React.Component<any, any> {
  constructor(props: any) {
    super(props);
    this.state = {
      active: false
    };
  }

  public render() {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

该应用程序无法启动以下编译错误:

Cannot assign to 'state' because it is a constant or a read-only property
Run Code Online (Sandbox Code Playgroud)

这是因为在定义中React.Component我们有:

readonly state: null | Readonly<S>;
Run Code Online (Sandbox Code Playgroud)

所以我不确定该怎么做.JS中的官方反应教程直接指定this.state并表示在构造函数中这样做是可接受的模式,但我无法弄清楚如何使用TypeScript执行此操作.

tor*_*vin 32

考虑到Typescript 不支持在派生构造函数中分配父的只读字段这一事实,这似乎是@types/react在commit 542f3c0中引入的最近的一个变化,它不能很好地工作.

我建议回滚到以前的版本@types/react.16.4.2在不幸的改变之前,版本似乎是最后一个版本.

您可以通过删除PIN码的版本^package.json:

"devDependencies": {
  ...
  "@types/react": "16.4.2",
Run Code Online (Sandbox Code Playgroud)

另请参阅DefinitelyTyped github pull请求页面上有关此更改的讨论


Nik*_*vić 31

在回滚之前(如@ torvin的回答所示),请阅读https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813#issuecomment-400795486.

这并不意味着回归 - 解决方案是state用作财产.它比以前的方法(state在构造函数中设置)更好,因为:

  • 你根本不需要构造函数
  • 你不能忘记初始化状态(现在是编译时错误)

例如:

type Props {}

type State {
  active: boolean
}

export default class Square extends React.Component<Props, State> {
  public readonly state: State = {
    active: false
  }

  public render() {
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法:

type Props {}

const InitialState = {
  active: false
}

type State = typeof InitialState

export default class Square extends React.Component<Props, State> {
  public readonly state = InitialState

  public render() {
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 好不好,当他们突然对次要版本升级引入重大变化时,会有点烦人 (25认同)
  • 只是想要注意,在此更改之前,您可以使用"状态作为属性"模式.这种变化的作用是什么 - 它迫使你使用它. (3认同)