J'essaie d'ajouter du filtrage à une application, mais mon gestionnaire de modifications ne semble pas faire référence à «ceci»? Une idée de ce que je fais mal ici?

class ShipmentList extends Component {
    constructor(props) {
        super(props)
        this.state = {
            shipments: [],
            searchString: '',
            loading: false
        }
    }

    handleChange(e){
    this.setState( {searchString:e.target.value} )   // <- This is where the error happens  
    }

    componentDidMount() {
        this.setState({loading: true})
        fetch('/shipments-server.json')
        .then(response => response.json())
        .then(shipments => this.setState({
            shipments,
            loading: false
        }))

    render() {
    const { shipments, loading, searchString } = this.state
    var shipmentData = shipments
    var filter = this.state.searchString

    if( filter.length > 0 ) {
        shipmentData = shipmentData.filter(s => {
            return s.carrierName.toLowerCase().match( filter.trim().toLowerCase() )
        });
    }


    return (
        <div className="shipment-list">
            <ul className="filters">
                <li><input value={this.state.searchString} onChange={this.handleChange} placeholder="Filter by Carrier" type="text" /></li>

Mes données se chargent correctement à partir du fichier JSON, mais lorsque je tape dans la zone de texte d'entrée et que la méthode handleChange () est appelée, je vois l'erreur `` Impossible d'obtenir la propriété 'setState' d'une référence non définie ou nulle ''. Lorsque je définis un point d'arrêt dans le code compilé, je peux voir que «ceci» n'est pas défini dans le cadre de la méthode handleChange () mais je n'ai aucune idée de pourquoi. Toute aide serait appréciée.

2
Miniversal 20 avril 2017 à 17:53

3 réponses

Meilleure réponse

Lorsque vous utilisez la nouvelle syntaxe de classe ES6, vous perdez la fonction de liaison automatique fournie par createClass. Cela a été un changement délibéré car les classes JavaScript ne font pas non plus de liaison automatique (le comportement est donc cohérent), vous pouvez en savoir plus ici: https://facebook.github.io/react/docs/react-without-es6.html#autobinding

Pour résoudre ce problème, vous pouvez soit revenir à l'ancienne syntaxe createClass, soit lier manuellement le contexte à votre méthode de deux manières:

  1. Utilisez bind() sur la méthode: <input onChange={this.handleChange.bind(this)} />
  2. Enveloppez dans une fonction de flèche: <input onChange={() => this.handleChange()} />
  3. Utilisez l'opérateur de liaison ES7 (nécessite une configuration Babel appropriée): <input onChange={::this.handleChange} />

Un petit problème avec ceci est que bind() et la déclaration de fonction de flèche (et probablement l'opérateur de liaison aussi, mais pas sûr à 100%) créeraient fondamentalement une nouvelle méthode, chaque fois que votre fonction render() est appelée . Cela a des implications sur les performances (bien que vous n'ayez généralement pas à vous en soucier). Si cela pose un problème, vous pouvez envisager d'affecter la méthode bornée à une variable lors de l'initialisation et de vous y référer. Quelque chose comme ça:

constructor(props) {
  // ...
  this.handleChange = this.handleChange.bind(this);
}

Ou, si votre configuration Babel permet la syntaxe des propriétés de classe, vous pouvez même éviter d'avoir à écrire des affectations comme celles-ci (et de déterminer quand vous en avez besoin), en utilisant simplement directement les fonctions fléchées pour tout:

class ShipmentList extends Component {

    handleChange = () => {
        // your handleChange code
    }
}
3
tkers 20 avril 2017 à 15:11

Vous n'avez pas de liaison le handleChange essayez-le comme ceci:

<input value={this.state.searchString} onChange={this.handleChange.bind(this)} placeholder="Filter by Carrier" type="text" />

Modifier 1

Tout comme @ fabian-schultz l'a souligné, vous pouvez également le faire dans le constructeur si vous êtes préoccupé par le succès de performance:

 constructor(props) {
        super(props)
        this.state = {
            shipments: [],
            searchString: '',
            loading: false
        }
       this.handleChange = this.handleChange.bind(this);
    }
2
Community 23 mai 2017 à 12:17

Vous devez lier this. Essayez ceci dans votre constructeur:

constructor(props) {
    super(props)
    this.state = {
        shipments: [],
        searchString: '',
        loading: false
    }
    this.handleChange = this.handleChange.bind(this);
}
2
Fabian Schultz 20 avril 2017 à 14:55