【问题标题】: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 来做到这一点。

【问题讨论】:

    标签: reactjs typescript types


    【解决方案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
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-10-14
        • 1970-01-01
        • 2019-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-24
        • 1970-01-01
        相关资源
        最近更新 更多