web-dev-qa-db-fra.com

Comment définir correctement l'état initial dans React avec TypeScript sans constructeur?

Dans JS moderne, nous pouvons directement définir un état initial pour un composant React comme ceci:

class App extends React.Component {
  state = {value: 10}

  render() {
    return <div>{this.state.value}</div>
  }
}

Quand j'essaie de faire cela avec TypeScript, TSLint dit "La propriété de classe 'state' doit être marquée 'private', 'public' ou 'protected'". Si je le mets à "privé", linter rapportera Class 'App' incorrectly extends base class 'Component<{}, { value: number; }, any>'. Property 'state' is private in type 'App' but not in type 'Component<{}, { value: number; }, any>'. sur App. Je suis conscient que je peux modifier les règles de linter pour ignorer ce type de vérification, mais vérifier la visibilité des propriétés de classe en général est une bonne chose que je souhaite utiliser.

Après avoir testé les trois options, seul le choix "public" n'entraînera pas d'erreurs de propagation de TSLint. Mais puisque l’état représente ici l’état interne de ce composant spécifique, le définir comme public semble plutôt étrange. Est-ce que je le fais correctement?

class App extends React.Component<{}, { value: number }> {
  public state = { value: 10 };

  public render() {
    return <div>{this.state.value}</div>;
  }
}

Dans tous les tutoriels TS-React que j'ai trouvés en ligne, un constructeur est utilisé, comme dans l'ancienne syntaxe JS.

class App extends React.Component<{}, { value: number }> {
  constructor(props: any) {
    super(props);
    this.state = { value: 10 };
  }

  public render() {
    return <div>{this.state.value}</div>;
  }
}

La définition de la propriété de classe est-elle directement considérée comme une mauvaise pratique/style dans Typescript?

3
John

Est-ce que je le fais correctement?

Oui.

La définition de la propriété de classe est-elle directement considérée comme un mauvais style dans Typescript?

Non.

Une approche légèrement meilleure

Envisagez de déclarer state en tant que public readonly et d'utiliser le modificateur Readonly .

Cela satisfera TSLint tout en vous offrant une certaine protection contre les modifications incorrectes (c'est-à-dire que vous n'utilisez pas this.setState) . Même si l'état est toujours exposé à l'extérieur, cela ne pose généralement pas de problème.

interface IState {
  value: number;
}

class App extends React.Component<{}, IState> {
  public readonly state: Readonly<IState> = {
    value: 10
  }

  public render() {
    return <div>{this.state.value}</div>
  }
}

La règle TSLint

Déclarer explicitement les modificateurs d'accès est une bonne chose, même si cela entraîne implicitement le même accès. Cela aide à garder votre code clair, donc je ne désactiverais pas cette règle TSLint.

8
rshepp

Je dirais que définir la propriété state d'un composant React directement est une pratique médiocre sauf si vous annotez que le type est identique au paramètre type d'état avec React.Component. Sans l'annotation, TypeScript détermine le type de this.state à partir de l'initialiseur, en remplaçant le type de la superclasse (qui est basé sur le paramètre type d'état) et ne vous donnera pas d'erreur si le type de l'initialiseur s'avère être un sous-type. du paramètre type. Cela peut entraîner des problèmes de santé ou un comportement inattendu plus tard; voir ce fil pour un exemple.

0
Matt McCutchen