2
votes

Je dois cliquer deux fois sur, le bouton pour afficher le composant

Dans ce composant de réaction, je souhaite afficher les données à l'écran lorsque l'utilisateur clique sur le bouton «Soumettre», mais il faut appuyer deux fois sur le bouton pour que les données s'affichent.

Voici mon code snippet:

class Invoice extends Component {
  constructor(props) {
    super(props);
    this.state = { items: [], isLoaded: false, transId: "" ,flag:true,errorFlag:false,show:false,displayContent:"",invoice:"",invoiceXmlBody:"",invoiceResult:"",invoiceTransId:"",invoiceResultFlag:false,invoicedisplayFlag:false};

  }
handleChangeInvoice(e) {
    console.log("inside handleChangeInvoice");
    let invoiceXml = e.target.value;
    if (invoiceXml !== undefined) {
      this.setState({ invoiceXmlBody: e.target.value });
    }
  }

  handleSubmitInvoiceXml =e=>{
   console.log("*******************inside handleSubmitInvoiceXml***************");
   let url = "http://localhost:8080/postInvoiceXml";
   fetch(url, {
    method: "POST",
    body: JSON.stringify(this.state.invoiceXmlBody),
     })
     .then(res => res.json()).then(data=>
       {
    this.setState({items:data});
    console.log(this.state.items[0].status);
     console.log("response========="+JSON.stringify(data));
      if(data===undefined){
          this.state.invoiceResultFlag=true;
    }
    else{
      this.state.invoicedisplayFlag=true;
          }
    }
 ) }

  render() {
    console.log("---------------------------"+this.state.invoicedisplayFlag);
    return (
      <div className="App">
        <br/>
          <label className="lable" style={{marginRight:19}}>
              InvoiceXml:
              <input
                type="text"
                name="invoiceXml" placeholder="Enter invoice xml"
                onBlur={this.handleChangeInvoice.bind(this)}  style={{marginLeft:15}} />

            </label><br/><br/>
             <input type="button" onClick={this.handleSubmitInvoiceXml} name="Submit" value="Submit" className="submitButton" />          
            <br/>
            <br/><br/>

            <div  className={this.state.invoicedisplayFlag?"showDisplay":"hide"}>
              {this.state.items.map((item,i) => (
                <div>
                <h2>Invoice No is: {item.invoiceNo}</h2>
                 <h2>Transaction id is: {item.transId}</h2>
                  <h2>Status: { item.status ? 'Success' : 'Failed' }</h2>
                 </div>
                       ))}
               </div>
       </div>
    );
  }
}

comment puis-je résoudre ce problème?


6 commentaires

Vous ne devez pas modifier l'état directement (comme this.state.invoiceResultFlag = .. ). Utilisez plutôt this.setState .


Avec "onDoubleClick", le composant n'est pas du tout rendu


@hindmost ... cela m'a aidé à résoudre le problème ... Pouvez-vous m'expliquer brièvement la raison derrière cela?


Attendez. Êtes-vous en train de dire que vous souhaitez afficher les données lorsque vous cliquez deux fois sur le bouton, ou que les données ne s'affichent que lorsque vous cliquez deux fois sur le bouton, mais ce n'est pas ce que vous voulez. Votre question n'est pas claire.


Mon problème était que les données lyk ne s'affichent que lorsque je clique deux fois sur le bouton, mais après avoir utilisé this.setState au lieu de modifier l'état directement, il a été résolu


Pouvez-vous m'expliquer brièvement la raison derrière cela? C'est un effet secondaire de la mutation directe de l'état.


3 Réponses :


2
votes

il est facile de trouver pourquoi, en gros vous définissez directement une valeur dans votre état, vous devez le faire en utilisant setState () comme le dit la documentation

donc votre code est:

this.setState({
    items:data,
    invoiceResultFlag: !data,
    invoicedisplayFlag: !!data,
});

mais il devrait be:

this.setState({items:data}, ()=>{
    if(data===undefined){
        this.setState({invoiceResultFlag: true})
    }
    else {
        this.setState({invoicedisplayFlag: true});
    }
});

Une autre chose que j'ai remarquée est que vous voulez définir un état après avoir défini un état, vous pouvez alors utiliser le rappel de setState ()

if(data===undefined){
    this.setState({invoiceResultFlag: true})
}
else {
    this.setState({invoicedisplayFlag: true});
}

et enfin, je n'aime pas personnellement ces 2 setState, ce serait plus facile de tout faire en un seul endroit:

if(data===undefined){
    this.state.invoiceResultFlag=true;
}
else {
    this.state.invoicedisplayFlag=true;
}


0 commentaires

0
votes

Dans la fonction onClick pour ce bouton, enregistrez simplement un drapeau dans l'état du composant [Ou local à votre classe] indiquant si le bouton a été cliqué et si c'est le cas, exécutez la logique de rendu ET réinitialisez le drapeau à nouveau


0 commentaires

0
votes

J'ai rencontré un problème similaire où j'utilisais onBlur pour mettre à jour l'état d'une valeur d'entrée.

J'ai trouvé que l'on avait changé onClick en onMouseDown pour fonctionner

<input className="input-form" onBlur={(e)=>{this.setState({field1:e.target.value})}/>

<button className="submit-button" onMouseDown={()=>{this.submitForm()}}>Submit</button>


0 commentaires