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

Posted

技术标签:

【中文标题】无法分配给“状态”,因为它是常量或只读属性【英文标题】:Cannot assign to 'state' because it is a constant or a read-only property 【发布时间】:2018-12-07 00:46:58 【问题描述】:

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

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

  public render() 
    ...
  

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

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

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

readonly state: null | Readonly<S>;

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

【问题讨论】:

【参考方案1】:

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

我建议回滚到以前版本的@types/react16.4.2 版本似乎是发生不幸更改之前的最后一个版本。

您可以通过删除package.json 中的^ 来固定版本:

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

还可以查看DefinitelyTyped github pull request page上有关此更改的讨论

【讨论】:

【参考方案2】:

在回滚之前(如@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() 
    //...
  

另一种方法:

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

【讨论】:

好与不好,当他们突然在次要版本升级中引入重大更改时,这有点烦人 只是想注意在此更改之前您可以使用“状态作为属性”模式。此更改的作用 - 它迫使您使用它。 我很想将此标记为已接受的答案,因为 Nikola 是正确的,这不是错误或回归,因此解决方案不应回滚,而应符合新标准。 @torvin,也许您应该编辑您的答案以包含此选项?我会在采取任何行动之前等待反馈 @jeanluc 两种方法都很好,但我认为将它们作为单独的答案更符合 SO 规则。我也喜欢这种方法,但它有缺点(请参阅this comment about forgetting readonly in derived classes)。另外请注意,readonly 修饰符已在以下pull request 中再次删除,并将很快推送到 npm。 看来此更改将在 @types/react 的另一个更新中被撤销,有关详细信息,请参阅此 pull request。目前,更简单的方法可能是遵循@torvin 的建议并回滚。【参考方案3】:

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

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

【讨论】:

以上是关于无法分配给“状态”,因为它是常量或只读属性的主要内容,如果未能解决你的问题,请参考以下文章

无法分配给对象的只读属性

C# NET 3.5:属性或索引器不能分配给“--”,它是只读的

属性或索引器不能分配给“”它是只读的[重复]

不能将属性或索引器“string.this[int]”分配给——它是只读的

TypeError:无法分配给只读属性 - Karma

Vue导入导致无法分配给对象错误的只读属性'exports'