Impossible de taper dans le champ de texte de saisie React

111

J'essaye mon premier morceau de React.js et je suis perplexe au début ... J'ai le code ci-dessous, qui rend un formulaire de recherche dans <div id="search"></div>. Mais taper dans le champ de recherche ne fait rien.

Il manque probablement quelque chose en passant les accessoires et l'état de haut en bas, et cela semble être un problème courant. Mais je suis perplexe - je ne vois pas ce qui manque.

var SearchFacet = React.createClass({
  handleChange: function() {
    this.props.onUserInput(
      this.refs.searchStringInput.value
    )
  },
  render: function() {
    return (
      <div>
        Search for:
        <input
          type="text"
          value={this.props.searchString}
          ref="searchStringInput"
          onchange={this.handleChange} />
      </div>
    );
  }
});

var SearchTool = React.createClass({
  render: function() {
    return (
      <form>
        <SearchFacet 
          searchString={this.props.searchString}
          onUserInput={this.props.onUserInput}
         />
        <button>Search</button>
      </form>
    );
  }
});

var Searcher = React.createClass({
  getInitialState: function() {
    return {
      searchString: ''
    }
  },

  handleUserInput: function(searchString) {
    this.setState({
      searchString: searchString
    })
  },

  render: function() {
    return (
      <div>
        <SearchTool 
          searchString={this.state.searchString}
          onUserInput={this.handleUserInput}
        />
      </div>
    );
  }
});

ReactDOM.render(
  <Searcher />,
  document.getElementById('searcher')
);

(Finalement, j'aurai d'autres types de SearchFacet*mais j'essaye juste de faire fonctionner celui-ci.)

Phil Gyford
la source
Essayez de vous connecter thislorsque vous saisissez le champ de texte. Il se peut que ce thisne soit plus le Searchercomposant.
FaureHu
Merci FaureHu - connexion thisà quel point dans le code? Essayer de se connecter Searcher.handleUserInput()ou SearchFacet.handleChange()ne fait rien.
Phil Gyford
vous pouvez voir ma réponse à des questions similaires. Vous pouvez trouver une explication détaillée: stackoverflow.com/questions/34713718/…
prudhvi seeramreddi

Réponses:

80

Vous n'avez pas correctement placé votre onchangeaccessoire dans le input. Il doit être onChangeen JSX.

<input
  type="text"
  value={this.props.searchString}
  ref="searchStringInput"
  onchange={this.handleChange} <--[should be onChange]
/>  

Le sujet du passage d'un valueaccessoire à un <input>, puis de la modification de la valeur transmise en réponse à l'interaction de l'utilisateur à l'aide d'un onChangegestionnaire est assez bien considéré dans la documentation .

Ils font référence à de telles entrées en tant que composants contrôlés et font référence à des entrées qui permettent au DOM de gérer nativement la valeur de l'entrée et les modifications ultérieures de l'utilisateur en tant que composants non contrôlés .

Chaque fois que vous définissez l' valueaccessoire d'un inputsur une variable, vous avez un composant contrôlé . Cela signifie que vous devez modifier la valeur de la variable par des moyens programmatiques ou bien l'entrée contiendra toujours cette valeur et ne changera jamais, même lorsque vous tapez - le comportement natif de l'entrée, pour mettre à jour sa valeur lors de la frappe, est remplacé par React ici.

Donc, vous prenez correctement cette variable de state, et avez un gestionnaire pour mettre à jour l'état tout mis en place correctement. Le problème était que vous aviez onchangeet non le bon, onChangele gestionnaire n'a jamais été appelé et donc le valuen'a jamais été mis à jour lorsque vous tapez dans l'entrée. Lorsque vous utilisez onChangele gestionnaire est appelé, le value est mis à jour lorsque vous tapez et vous voyez vos modifications.

Davnicwil
la source
201

En utilisant value={whatever}, vous ne pourrez pas taper dans le champ de saisie. Vous devriez utiliser defaultValue="Hello!".

Voir https://facebook.github.io/react/docs/uncontrolled-components.html#default-values

De plus, le onchangedevrait être onChangecomme le souligne @davnicwil.

Ivan
la source
2
Dans mon exigence, je voulais saisir un champ avec activation de la saisie et il doit être défini sur la valeur par défaut provenant d'une variable d'état. L'attribut defaultValue était correct mais il y a un problème de mise à jour de la valeur par défaut en fonction des changements d'état, y a-t-il un moyen de forcer la valeur par défaut à changer?
semira
1
Vous devriez publier ce problème comme une autre question sur Stackoverflow.
Ivan
1
@GeoffreyHale Je ne suis pas tout à fait sûr de ce que vous entendez par la façon dont c'est trompeur. Voir cet exemple qui n'utilise pas state: codepen.io/anon/pen/BQJZwr?editors=0010 . Ou celui-ci qui fait: codepen.io/anon/pen/JbMJMX?editors=0010
Ivan
4
@Ivan Vous avez raison, les deux sont immuables: value={whatever}et value={this.state.myvalue}. J'aurais dû faire cette clarification à la place: utiliser onChange={this.handleChange}et quelque chose comme ça handleChange: function(e) { var newState = {}; newState[e.target.name] = e.target.value; this.setState(newState); },rend les champs à nouveau mutables.
Geoffrey Hale
1
@Ivan Celui-ci vient de m'aider Merci beaucoup defaultValuesauve ma journée.
Code Cooker
11

Cela peut être dû au fait que la fonction onChange ne met pas à jour la valeur appropriée mentionnée dans l'entrée.

Exemple:

<input type="text" value={this.state.textValue} onChange = {this.changeText}></input>

 changeText(event){
        this.setState(
            {textValue : event.target.value}
        );
    }

dans la fonction onChange, mettez à jour le champ de valeur mentionné.

sunaina kotekar
la source
Merci, très utile. Seule votre réponse explique en détail comment résoudre le problème.
M3RS
où définir cette fonction changeText?
Jitendra Pancholi
S'il s'agit d'un composant sans état, à l'intérieur de la fonction, et s'il s'agit d'un composant de classe, à l'intérieur du constructeur.
Gal Grünfeld
vous n'avez pas besoin d'écrire this.state dans le setState. Si vous n'écrivez que textValue: event.target.value dans setState, cela fonctionne aussi parfaitement
Pardeep Sharma
4

J'ai aussi le même problème et dans mon cas, j'ai injecté correctement le réducteur mais je ne pouvais toujours pas taper dans le champ. Il s'avère que si vous utilisez, immutablevous devez utiliser redux-form/immutable.

import {reducer as formReducer} from 'redux-form/immutable';
const reducer = combineReducers{

    form: formReducer
}
import {Field, reduxForm} from 'redux-form/immutable';
/* your component */

Notez que votre état doit être le même, state->formsinon vous devez configurer explicitement la bibliothèque, ainsi que le nom de l'état form. voir ce numéro

Seyed Jalal Hosseini
la source
4

Pour moi, le simple changement suivant a parfaitement fonctionné

<input type="text" 
        value={props.letter} 
        onChange={event => setTxtLetter(event.target.value)} /> {/* does not work */}

changer ... value = {myPropVal} en ... defaultValue = {myPropVal}

<input type="text" 
        defaultValue={props.letter} 
        onChange={event => setTxtLetter(event.target.value)} /> {/* Works!! */}
Nelles
la source
Cela a résolu le problème pour moi, merci!
mikeym
Je pense que onChange ne fonctionne pas correctement lorsqu'il est utilisé dans Formik. J'essayais cela aussi mais cela n'a pas fonctionné pour moi. Pourriez-vous s'il vous plaît jeter un oeil ici? stackoverflow.com/questions/61689720/…
a125
0

Dans un contexte de composant de classe ...

Si la méthode changeHandler est une fonction normale:

handleChange(e){
    this.setState({[e.target.name]:[e.target.value]});
}

il peut être utilisé comme ça ...onChange={(e)=>this.handleChange(e)}

<input type="text" name="any" value={this.state.any} onChange={(e)=>this.handleChange(e)}></input>

Si la méthode changeHandler est une fonction de flèche:

handle = (e) =>{
        this.setState({[e.target.name]:[e.target.value]});
    }

il peut être utilisé comme ça ... onChange={this.handle}

 <input type="text" name="any2" value={this.state.any2} onChange={this.handle} ></input>

Et cela a résolu mon problème "Impossible de taper dans le champ de texte de saisie React".

Aditya Patnaik
la source