web-dev-qa-db-fra.com

React: déclencher onChange si la valeur d'entrée change d'un état à l'autre?

Edit: Je ne veux pas appeler handleChange uniquement si le bouton a été cliqué. Cela n'a rien à voir avec handleClick. J'ai donné un exemple dans le commentaire de la réponse @shubhakhatri.

Je veux changer la valeur d'entrée en fonction de l'état, la valeur est en train de changer mais elle ne déclenche pas la méthode handleChange(). Comment déclencher la méthode handleChange()

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    value: 'random text'
    }
  }
  handleChange (e) {
    console.log('handle change called')
  }
  handleClick () {
    this.setState({value: 'another random text'})
  }
  render () {
    return (
      <div>
        <input value={this.state.value} onChange={this.handleChange}/>
        <button onClick={this.handleClick.bind(this)}>Change Input</button>
      </div>
    )
  }
}

ReactDOM.render(<App />,  document.getElementById('app'))

Voici le lien vers le code: http://codepen.io/madhurgarg71/pen/qrbLjp

15
madhurgarg

Vous devez déclencher l'événement onChange manuellement. Sur les entrées de texte, onChange écoute les événements input.

Donc, dans votre fonction handleClick, vous devez déclencher un événement tel que 

handleClick () {
    this.setState({value: 'another random text'})
    var event = new Event('input', { bubbles: true });
    this.myinput.dispatchEvent(event);
  }

Code complet

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    value: 'random text'
    }
  }
  handleChange (e) {
    console.log('handle change called')
  }
  handleClick () {
    this.setState({value: 'another random text'})
    var event = new Event('input', { bubbles: true });
    this.myinput.dispatchEvent(event);
  }
  render () {
    return (
      <div>
        <input readOnly value={this.state.value} onChange={(e) => {this.handleChange(e)}} ref={(input)=> this.myinput = input}/>
        <button onClick={this.handleClick.bind(this)}>Change Input</button>
      </div>
    )
  }
}

ReactDOM.render(<App />,  document.getElementById('app'))

Codepen

Edit: Comme suggéré par @Samuel dans les commentaires, un moyen plus simple serait d’appeler handleChange de handleClick si vous don't need to the event object dans handleChange comme

handleClick () {
    this.setState({value: 'another random text'})
    this.handleChange();
  }

J'espère que c'est ce dont vous avez besoin et que cela vous aide.

15
Shubham Khatri

Je pense que tu devrais changer ça comme ça:

<input value={this.state.value} onChange={(e) => {this.handleChange(e)}}/>

C'est en principe le même que onClick={this.handleClick.bind(this)} comme vous l'avez fait pour le bouton. 

Donc, si vous voulez appeler handleChange() quand le bouton est cliqué, alors:

<button onClick={this.handleChange.bind(this)}>Change Input</button>

ou

handleClick () {
  this.setState({value: 'another random text'});
  this.handleChange();
}
4
philipp

Les autres réponses ont parlé de liaison directe dans le rendu et je voudrais donc ajouter quelques points à ce sujet.

Il n'est pas recommandé de lier la fonction directement dans render ou ailleurs dans le composant, sauf dans le constructeur. Parce que pour chaque liaison de fonction, une nouvelle fonction/un objet sera créé dans le fichier js de Webpack Bundle, ce qui augmentera la taille de celui-ci. Votre composant effectuera un nouveau rendu pour différentes raisons, telles que lorsque vous définissez setState, les nouveaux accessoires reçus, this.forceUpdate(), etc. Ainsi, si vous liez directement votre fonction dans le rendu, elle créera toujours une nouvelle fonction. Au lieu de cela, reliez toujours la fonction au constructeur et appelez la référence si nécessaire. De cette façon, il ne crée une nouvelle fonction qu'une seule fois car le constructeur n'est appelé qu'une seule fois par composant.

Comment faire comme ci-dessous

constructor(props){
  super(props);
  this.state = {
    value: 'random text'
  }
  this.handleChange = this.handleChange.bind(this);
}

handleChange (e) {
  console.log('handle change called');
  this.setState({value: e.target.value});
}

<input value={this.state.value} onChange={this.handleChange}/>

Vous pouvez également utiliser des fonctions de flèche, mais ces dernières créent également une nouvelle fonction à chaque fois que le composant effectue un nouveau rendu dans certains cas. Vous devriez savoir quand utiliser la fonction flèche et quand ne le supposons pas. Pour des explications détaillées sur le moment d'utiliser les fonctions de flèche, vérifiez la réponse acceptée ici

0
Hemadri Dasari

vous devez faire 4 étapes suivantes:

  1. créer un évènement

    var event = new Event("change",{
        detail: {
            oldValue:yourValueVariable,
            newValue:!yourValueVariable
        },
        bubbles: true,
        cancelable: true
    });
    event.simulated = true;
    let tracker = this.yourComponentDomRef._valueTracker;
    if (tracker) {
        tracker.setValue(!yourValueVariable);
    }
    
  2. lie la valeur au composant dom

    this.yourComponentDomRef.value = !yourValueVariable;
    
  3. lier l’élément onchange à la fonction onChange

     this.yourComponentDomRef.onchange = (e)=>this.props.onChange(e);
    
  4. événement d'expédition

    this.JBSwitchComponentDom.dispatchEvent(event);
    

dans le code ci-dessus, yourComponentDomRef, reportez-vous au dom maître de votre composant React pour obtenir l'exemple <div className="component-root-dom" ref={(dom)=>{this.yourComponentDomRef= dom}}>.

0
javad bat

Je sais ce que vous voulez dire, vous voulez déclencher handleChange par clic.

Mais la valeur de l'état de modification ne déclenchera pas l'événement onChange, car l'événement onChange est un événement d'élément de formulaire.

0
Xat_MassacrE

handleChange est appelé ('changement de poignée appelé' est imprimé dans la console) mais il ne met pas à jour l'état Vous devez mettre à jour l'état dans votre gestionnaire de modifications:

handleChange (e) {
    console.log('handle change called');
    this.setState({value: e.target.value});
}

et vous devez également lier le contexte au gestionnaire:

<input value={this.state.value} onChange={this.handleChange.bind(this)}/>
0
Bartek Fryzowicz