2017-10-09 7 views
1

L'étiquette est modifiable: Lorsque vous cliquez sur l'étiquette, le champ de texte d'entrée s'affiche et le champ d'étiquette est masqué. Après que le champ de texte a perdu le focus, le champ d'étiquette sera affiché et le champ de texte sera caché. J'ai un problème où le label ne se met pas à jour avec la nouvelle valeur d'entrée de texte.Pourquoi mon étiquette d'affichage/masquage React ne se met-elle pas correctement à jour?

Le bouton Ajouter un composant créera un nouveau composant et le placera en haut de la liste. Avoir un problème où le composant nouvellement créé est placé au-dessous de la liste qui a le texte d'entrée montré et l'étiquette cachée.

Après avoir ajouté plusieurs nouveaux composants, lorsque je clique sur l'un des libellés, le champ de texte est automatiquement mis à jour avec un autre texte. J'ai essayé de le déboguer mais je ne peux pas le résoudre.

import React from 'react'; 
import FontAwesome from 'react-fontawesome'; 

export default class Dynamic extends React.Component { 
    constructor() { 
    super(); 
    this.state = { 
     arr: [], 
     text:"LABEL", 
     saveDisabled: true, 
     editing: [] 
    }; 
    } 

    handleSort(sortedArray) { 
    this.setState({ 
     arr: sortedArray 
    }); 
    } 

    save(){ 
    } 

    closePopup() { 
    } 

    handleAddElement() { 
    this.textInput.value : 'LABEL'; 
    this.state.arr.unshift('LABEL'); 

    this.setState({ 
     saveDisabled: false, 
    }); 
    } 

    handleRemoveElement(index) { 
    const newArr = this.state.arr.slice(); 
    newArr.splice(index, 1); 

    this.setState({ 
     arr: newArr, 
     saveDisabled: false 
    }); 
    } 

    changeLabel(index){  
    this.setState({ 
     saveDisabled: false 
    }); 
    console.log(index); 
    this.state.editing[index] = true; 
    console.log("changelabel"); 
    } 

    textChanged(index) { 
    console.log("txtval: "+this.textInput.value); 
    this.setState({ text: this.textInput.value}); 
    this.state.arr[index] = this.textInput.value; 
    this.setState({ 
     arr: arr 
    }); 
    console.log(this.state.arr); 
    } 

    inputLostFocus(index) { 
    this.state.editing[index] = false; 
    } 

    keyPressed(event) { 
    if(event.key == 'Enter') { 
     this.inputLostFocus(); 
    } 
    this.inputLostFocus(); 
    console.log("key"); 
    } 

    render() { 
    function renderItem(num, index) { 

     return ( 
      <DemoItem className="dynamic-item" > 
       <FontAwesome className='th' name=' th' onClick={this.handleRemoveElement.bind(this, index)}/> 
       <div name="name" className={(index==0)||this.state.editing[index] ? "hideElement": "displayElement"} onClick={this.changeLabel.bind(this,index)}>{this.state.arr[index]}</div> 
       <input autofocus name="name" type="text" className={(index==0)||this.state.editing[index] ? "displayElement": "hideElement"} onChange={this.textChanged.bind(this, index)} onBlur={this.inputLostFocus.bind(this,index)} 
       onKeyPress={this.keyPressed.bind(this,index)} defaultValue={this.state.arr[index]} ref={(input) => {this.textInput = input;}} /> 
       <FontAwesome className='trash-o' name='trash-o' onClick={this.handleRemoveElement.bind(this, index)}/> 
     </DemoItem> 
     ) 
    } 

    return ( 
     <div className="demo-container"> 
     <div className="dynamic-demo"> 
      <h2 className="demo-title"> 
      Tasks 
      <button disabled={this.state.saveDisabled} onClick={::this.save}>Save</button> 
      <button onClick={::this.handleAddElement}>Add Component</button> 
      </h2> 
      <Sortable className="vertical-container" direction="vertical" dynamic> 
      {this.state.arr.map(renderItem, this)} 
      </Sortable> 
     </div> 
     </div> 
    ); 
    } 
} 


displayElement { 
    display: inline; 
} 
.hideElement{ 
    display: none; 
} 

Répondre

1

Il semble que votre bug est dans votre fonction textChanged, essayez ceci:

textChanged(index) { 
 
    console.log("txtval: " + this.textInput.value); 
 
    // this.state.arr[index] = this.textInput.value; <= bug 
 
    const newArray = [...this.state.arr]; 
 
    newArray[index] = this.textInput.value; 
 
    this.setState({ 
 
    arr: newArray, 
 
    text: this.textInput.value 
 
    }); 
 
    // console.log(this.state.arr); <= don't check here, check in your render method 
 
}

Deux changements:

  1. Modifier l'état via this.setState, pas via this.state.arr.
  2. Définition de l'état en une action this.setState pour le code de nettoyage.
  3. Commenter le journal de la console de this.state car l'état n'a pas encore été entièrement mis à jour jusqu'au prochain cycle de vie. Au lieu de cela, consignez l'état de la console dans votre méthode de rendu.
+0

Salut Scott, merci pour vos conseils! C'est très utile. J'essaie de déboguer, la fonction pour textChanged (index) fait référence à this.textInput.value qui ne correspond pas à l'index de tableau correct. Savez-vous si je peux définir un identifiant/nom de classe spécifique pour chaque champ de saisie, car j'utilise {this.state.arr.map (renderItem, this)} pour rendre les composants répétés dans le renderItem() – user21

+0

Oui, vous peut définir des valeurs de référence spécifiques pour chaque champ de saisie. Autant que vous voulez. Ai-je répondu à votre question et pouvez-vous accepter ma réponse? – Scott