web-dev-qa-db-fra.com

Impossible d'affecter à 'state' car il s'agit d'une propriété constante ou en lecture seule

Lorsque je fais une recherche sur ce problème, je ne trouve que des questions qui modifient this.state directement quelque part dans le corps d'une méthode au lieu d'utiliser this.setState(). Mon problème est que je veux définir un état de départ dans le constructeur comme suit:

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

  public render() {
    ...
  }
}

L'application ne parvient pas à démarrer avec l'erreur de compilation suivante:

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

Et ceci parce que dans la définition de React.Component nous avons:

readonly state: null | Readonly<S>;

Je ne suis donc pas sûr de savoir comment s'y prendre. Le didacticiel de réaction officiel de JS attribue directement à this.state et indique qu'il est acceptable de le faire dans le constructeur, mais je ne vois pas comment procéder avec TypeScript.

36
jeanluc

Cela semble être un changement récent dans @types/react introduit dans commit 542f3c qui ne fonctionne pas très bien, compte tenu du fait que TypeScript ne prend pas en charge assignant le parent champs en lecture seule dans les constructeurs dérivés.

Je suggère de revenir à une version précédente de @types/react. La version 16.4.2 semble être la dernière avant la modification malheureuse.

Vous pouvez épingler la version en supprimant le ^ de votre package.json:

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

Consultez également la discussion à propos de cette modification sur page de demande d'extraction de github de DefinitelyTyped

30
torvin

Avant de revenir en arrière (comme suggéré par la réponse de @ torvin), veuillez lire attentivement https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813#issuecomment-400795486 .

Cela ne devait pas être une régression - la solution consiste à utiliser state en tant que propriété . C'est mieux que l'approche précédente (régler state dans un constructeur) parce que:

  • vous n'avez plus besoin du constructeur
  • vous ne pouvez pas oublier d'initialiser l'état (c'est maintenant une erreur de compilation)

Par exemple:

type Props {}

type State {
  active: boolean
}

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

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

Une autre approche:

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() {
    //...
  }
}
30
Nikola Mihajlović