web-dev-qa-db-fra.com

React Native: this.setState n'est pas une fonction

Je vois un certain nombre de questions sur ce même sujet, mais il semble qu'aucune ne corresponde à mon problème et est un peu plus complexe.

Je suis en train d'apprendre ReactJS et React Native. Je suis en train de lire et de suivre les exemples de code du livre "Learning React Native" ici: https://github.com/bonniee/learning-react-native

Pour une raison quelconque, l'appel de this.setState dans le code ci-dessous lorsque la fonction handleTextChange est appelée, provoque le message "this.SetState n'est pas une fonction". Erreur. Ma question est pourquoi? Contrairement à d'autres questions sur ce même problème, je ne crois pas que mon appel à this.stateState soit enterré dans une fonction de rappel ou une instruction if. Pourquoi est-ce indéfini?

Voici mon code:

class WeatherProject extends Component {
  constructor(props) {
    super(props);
    this.state = {
      Zip: "",
      forecast: null
    };
  }

  _handleTextChange(event) {
    this.setState({Zip: event.nativeEvent.text});
  }

    render() {
    return (
      <View style={styles.container}>
      <Text style={styles.welcome}>
      You input {this.state.Zip}.
      </Text>
      <TextInput
      style={styles.input}
      onSubmitEditing={this._handleTextChange}/>
      </View>
    );
  }
}
23
William C

N'utilisez pas bind dans un rendu. bind est une opération assez coûteuse et ne devrait se produire qu’une fois. vous avez deux options:

soit lier la fonction dans le constructeur:

this._handleTextChange = this._handleTextChange.bind(this);

ou utilisez la fonction flèche:

onSubmitEditing={(e) => this._handleTextChange(e)} />

Modifier

Apparemment, les fonctions de flèche dans le rendu sont également une mauvaise pratique (merci à Adam Terlson dans les commentaires et réponses ci-dessous). Vous pouvez lire eslint docs qui dit:

Un appel de liaison ou une fonction de flèche dans un accessoire JSX créera une nouvelle fonction pour chaque rendu. Cela est mauvais pour les performances, car le ramasse-miettes sera invoqué bien plus que nécessaire.

L'utilisation de fonctions fléchées n'est évidemment pas aussi mauvaise que l'utilisation de bind, mais doit néanmoins être évitée.

42
atlanteh

En ce qui concerne la fonction de flèche, vous devez également modifier la fonction _handleTextChange (event). D'autres réponses n'ont pas parlé de la façon de changer la fonction normale en fonction de flèche. Donc, fournir une réponse qui puisse aider les autres

Vous devez changer la fonction du gestionnaire

de

_handleTextChange(event) {
    this.setState({Zip: event.nativeEvent.text});
  }

À

_handleTextChange = event => {
   this.setState({Zip: event.nativeEvent.text});
 }
12
Hemadri Dasari

La question est liée au contexte, comme indiqué dans les autres commentaires et réponses ici.

Cependant, la performance de bind elle-même n'est pas un problème. La question la plus pertinente est que l’utilisation de bind ou de flèches dans vos méthodes de rendu crée une nouvelle fonction sur chaque rendu, ce qui entraîne un changement des accessoires pour l'enfant qui les reçoit, forçant un re-rendu.

Vous avez deux options viables:

class WeatherProject extends Component {
  constructor(props) {
    super(props);

    this._handleTextChange = this._handleTextChange.bind(this);
  }
  // ...
}

Vous pouvez également utiliser la notation de propriété de classe et attribuer des fonctions de flèche si vous utilisez le plugin babel .

class WeatherProject extends Component {
  constructor(props) {
    super(props);
    // ...
  }

  handleTextChange = (event) => {
    this.setState({Zip: event.nativeEvent.text});
  }
  // ...
}

Je vous recommande fortement d'utiliser le paquet eslint avec l'option réagir aux règles recommandées activée. Il détectera des erreurs telles que l'utilisation de liens/flèches dans votre rendu, et vous indiquera également que les fonctions préfixées de soulignement sont laides et totalement inutiles dans React. :)

7
Adam Terlson