La propriété 'value' n'existe pas sur le type 'Readonly <{}>'


155

J'ai besoin de créer un formulaire qui affichera quelque chose en fonction de la valeur de retour d'une API. Je travaille avec le code suivant:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value); //error here
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} /> // error here
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

J'obtiens l'erreur suivante:

error TS2339: Property 'value' does not exist on type 'Readonly<{}>'.

J'ai eu cette erreur dans les deux lignes que j'ai commentées sur le code. Ce code n'est même pas le mien, je l'ai obtenu sur le site officiel de react ( https://reactjs.org/docs/forms.html ), mais il ne fonctionne pas ici.

J'utilise l'outil create-react-app.


Votre problème est ailleurs - voir cette démo
Ted

Je sais, cela fonctionne sur tous ces sites Web de "compilateurs", mais ils m'ont conseillé de l'utiliser pour faire le projet github.com/Microsoft/TypeScript-React-Starter , et via le compliteur TypeScript, cela ne fonctionne pas
Luis Henrique Zimmermann

Réponses:


264

Le Component est défini comme ceci:

interface Component<P = {}, S = {}> extends ComponentLifecycle<P, S> { }

Ce qui signifie que le type par défaut pour l'état (et accessoires) est: {}.
Si vous voulez que votre composant soit valuedans l'état, vous devez le définir comme ceci:

class App extends React.Component<{}, { value: string }> {
    ...
}

Ou:

type MyProps = { ... };
type MyState = { value: string };
class App extends React.Component<MyProps, MyState> {
    ...
}

3
omg, ty mec, ça a fonctionné maintenant, répondez-moi encore une chose, cette syntaxe est liée à TypeScript, non? car sur le site officiel de React, il n'y a rien de similaire
Luis Henrique Zimmermann

3
Oui, c'est strictement lié à la dactylographie.
Nitzan Tomer

1
La bonne définition est la suivante: class Square extend React.Component <{value: string}, {}> {...}
Rodrigo Perez Burgues

58

En plus de la réponse de @ nitzan-tomer, vous avez également la possibilité d'utiliser des inferfaces :

interface MyProps {
  ...
}

interface MyState {
  value: string
}

class App extends React.Component<MyProps, MyState> {
  ...
}

// Or with hooks, something like

const App = ({}: MyProps) => {
  const [value, setValue] = useState<string>(null);
  ...
};

Les deux sont bien, tant que vous êtes cohérent.


1
Veuillez résumer ce que signifie cohérent dans le contexte de votre message afin qu'il soit possible d'avoir toute sa valeur sans avoir besoin de lire l'article médium (qui est un excellent lien utile, merci).
Karl Richter

9

Le problème est que vous n'avez pas déclaré l'état de votre interface, remplacez-les par le type de variable approprié de la 'valeur'

Voici une bonne référence

interface AppProps {
   //code related to your props goes here
}

interface AppState {
   value: any
}

class App extends React.Component<AppProps, AppState> {
  // ...
}

0

event.targetest d'un type EventTargetqui n'a pas toujours de valeur. S'il s'agit d'un élément DOM, vous devez le convertir dans le type correct:

handleChange(event) {
    this.setState({value: (event.target as HTMLInputElement).value});
}

Cela permettra également de déduire le type "correct" de la variable d'état, bien qu'il soit probablement préférable d'être explicite


Je pense qu'il obtient l'erreur lorsqu'il tente d'initialiser la chaîne dans le constructeur, pas le gestionnaire d'événements
Ray_Poly
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.