typescript 无法分配给“状态”,因为它是常量或只读属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51074355/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:30:13  来源:igfitidea点击:

Cannot assign to 'state' because it is a constant or a read-only property

reactjstypescripttypes

提问by jeanluc

When I do a search on this issue, I can only find questions that modify this.statedirectly somewhere in a method body instead of using this.setState(). My problem is that I want to set a starting state in the constructor as follows:

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

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

  public render() {
    ...
  }
}

The app fails to start with the following compile error:

应用程序无法启动,出现以下编译错误:

Cannot assign to 'state' because it is a constant or a read-only property

And this is because in definition of React.Componentwe have:

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

readonly state: null | Readonly<S>;

So I'm not sure how to go about this. The official react tutorial in JS directly assigns to this.stateand says that it is an acceptable pattern to do so in the constructor, but I can't figure out how to do this with TypeScript.

所以我不知道该怎么做。JS 中的官方 react 教程直接分配给this.state并说在构造函数中这样做是一种可接受的模式,但我无法弄清楚如何使用 TypeScript 来做到这一点。

采纳答案by torvin

This appears to be a recent change in @types/reactintroduced in commit 542f3c0which doesn't work very well, considering the fact that Typescript doesn't supportassigning parent's readonly fields in derived constructors.

这似乎是@types/react提交542f3c0中引入的最近更改,考虑到 Typescript不支持在派生构造函数中分配父级的只读字段这一事实,该更改效果不佳。

I suggest rolling back to a previous version of @types/react. Version 16.4.2appears to be the last one before the unfortunate change has been made.

我建议回滚到@types/react. 版本16.4.2似乎是进行不幸更改之前的最后一个版本。

You can pin the version by removing the ^in your package.json:

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

"devDependencies": {
  ...
  "@types/react": "16.4.2",

Also check out the discussion about this change on DefinitelyTyped github pull request page

另请查看关于此更改的讨论绝对类型 github 拉请求页面

回答by Nikola Mihajlovi?

Before rolling back (as suggested by @torvin's answer), please read through https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813#issuecomment-400795486.

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

This was not meant to be a regression - the solution is to use stateas a property. It is better than previous approach (setting statein a constructor) because:

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

  • you don't need constructor at all anymore
  • you can't forget to initialize state (it is now a compile-time error)
  • 你根本不需要构造函数了
  • 你不能忘记初始化状态(它现在是一个编译时错误)

For example:

例如:

type Props {}

type State {
  active: boolean
}

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

  public render() {
    //...
  }
}

Another approach:

另一种方法:

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() {
    //...
  }
}

回答by Michael Landis

Because stateis a readonly property of the component, it can't be set field-by-field, but you can still do:

因为state是组件的只读属性,所以不能逐字段设置,但你仍然可以这样做:

constructor(props: MyProps) {
  super(props);
  this.state = {
    // include properties here
  }
}