web-dev-qa-db-fra.com

obtenir une erreur: Impossible de lire l'état de la propriété non défini

import React, { Component } from "react";
import FormUpdate from "../components/formUpdate";
import { fetchClothingItem, updateClothingItem } from "../actions/crud";

export default class Update extends Component {
    constructor(props) {
        super(props);

        this.state = {
          updateClothingItem: {}
        };
    }

    componentWillMount() {
        fetchClothingItem(this.props.match.params.postId)
        .then(data => {
        this.setState(state => {
          state.updateClothingItem = data;
          return state;
        });
        console.log("data", data);

        //HERE IT IS RETURNING EXPECTED DATA       

        console.log("this.state.updateClothingItem",this.state.updateClothingItem)    
          })
        .catch(err => {
            console.error("err", err);
        });
    }

    handleSubmit(data) {

        //HERE IT IS THROWING: 

        > "TypeError: Cannot read property 'state' of undefined"

        console.log("this.state.updateClothingItem", this.state.updateClothingItem);
            updateClothingItem(this.state.updateClothingItem.id, data); this.props.router.Push("/update");
    }
    render() {
        return (
        <div>
        <FormUpdate
          //onSubmit={this.handleSubmit.bind(this)}
          id={this.state.updateClothingItem.id}
          name={this.state.updateClothingItem.name}
          sleeveLength={this.state.updateClothingItem.sleeveLength}
          fabricWeight={this.state.updateClothingItem.fabricWeight}
          mood={this.state.updateClothingItem.body}
          color={this.state.updateClothingItem.color}
        />
        <button
          type="submit"
          onClick={this.handleSubmit}
          className="addItemButton"
        >
        Button
        </button>
      </div>
    );
  }
}
7
Colton Dowling

Il y a quelques choses qui sont techniquement incorrectes en termes d'implémentation du code React.

Premièrement, Avec le style d'écriture ES6 d'une classe, toute fonction devant accéder aux propriétés de la classe doit être explicitement binded. Dans votre cas, vous devez lier la fonction handleSubmit à l'aide de arrow function of ou binding in constructor

Voir cette réponse pour plus de détails: Pourquoi et quand avons-nous besoin de lier des fonctions et des gestionnaires d'événements dans React?

Deuxièmement: Votre demande asynchrone est configurée dans la fonction composantWillMount et, dans la réponse de réussite de celle-ci, vous définissez l'état. Toutefois, l'utilisation de setState dans componentWillMount étant déclenchée après le rendu du composant, vous devez toujours effectuer une vérification non définie. Vous devriez plutôt utiliser la fonction componentDidMount lifecycle pour les demandes asynchrones.

Cochez cette réponse pour savoir si vous devez avoirAJAX une requête dans componentDidMount ou componentWillMount

Troisième: setState est asynchrone et par conséquent, la consignation des valeurs d'état après la fonction setState n'entraînera pas l'affichage de la sortie correcte. Utilisez le setState callback à la place. 

Voir ces réponses pour plus de détails: 

l'appel de setState ne mute pas immédiatement

Quand utiliser le rappel React setState

Code:

export default class Update extends Component {
    constructor(props) {
        super(props);

        this.state = {
          updateClothingItem: {}
        };
    }

    componentDidMount() {
        fetchClothingItem(this.props.match.params.postId)
        .then(data => {
        this.setState(state => {
          state.updateClothingItem = data;
          return state;
        });
        console.log("data", data);

        //HERE IT IS RETURNING EXPECTED DATA       

        console.log("this.state.updateClothingItem",this.state.updateClothingItem)    
          }) // this statement will not show you correct result since setState is async 
        .catch(err => {
            console.error("err", err);
        });
    }

    handleSubmit = (data) =>  { .    // binding using arrow function here

        console.log("this.state.updateClothingItem", this.state.updateClothingItem);
            updateClothingItem(this.state.updateClothingItem.id, data); this.props.router.Push("/update");
    }
    render() {
        return (
        <div>
        <FormUpdate
          //onSubmit={this.handleSubmit.bind(this)}
          id={this.state.updateClothingItem.id}
          name={this.state.updateClothingItem.name}
          sleeveLength={this.state.updateClothingItem.sleeveLength}
          fabricWeight={this.state.updateClothingItem.fabricWeight}
          mood={this.state.updateClothingItem.body}
          color={this.state.updateClothingItem.color}
        />
        <button
          type="submit"
          onClick={this.handleSubmit}
          className="addItemButton"
        >
        Button
        </button>
      </div>
    );
  }
}
6
Shubham Khatri

Vous avez oublié de lier votre fonction handleSubmit à la classe. Vous pouvez soit utiliser la fonction flèche pour définir la fonction.

handleSubmit=(data) =>{
...
}

Ou vous pouvez lier la fonction dans votre constructeur.

constructor(props) {
        super(props);
        this.state = {
          updateClothingItem: {}
        };
        this.handleSubmit= this.handleSubmit.bind(this,data);
    }
1
palsrealm

il n'y a pas encore d'état constructeur

si vous voulez définir l'état dans le constructeur, vous pouvez le faire comme ceci

class SomeComponent extends Component {
   constructor(props){
      super(props)

      this.state = { ... }
   }
}

ou même comme ça

class SomeComponent extends Component {

   state = {  }

}

mais dans ce cas, babel doit être correctement configuré

0
Denis Rudov