Hello. There are two buttons. Depending on which button I clicked, the text fields with the data are rendered.

var Data = [1, 2, 3]; var Test = ['Vasya', 'Kate', 'TEst']; var Main = React.createClass({ getInitialState: function () { return { inputs: null } }, _getData: function () { this.setState({ inputs: Data }); }, _getTest: function () { this.setState({ inputs: Test }); }, createBtnData: function () { return <button onClick={this._getData}>Get Data</button>; }, createBtnTest: function () { return <button onClick={this._getTest}>Get Test</button>; }, _changeValue: function (e) { var val = e.target.value; this.setState({ inputs: val }); }, createInput: function () { if (this.state.inputs) { return this.state.inputs.map(function (item, i) { return <input key={i} value={item} onChange={this._changeValue} /> }.bind(this)); } }, render: function() { return <div> {this.createBtnData()} {this.createBtnTest()} {this.createInput()} </div>; } }); 

The problem is that when I click on one of the fields and try to enter text, the following error is caused:

TypeError: this.state.inputs.map is not a function

I understand that the problem is that the map method is trying to be called again for the data that I enter, and since this is not an array, but a string, this is where the error comes from.

Question: how in this case should I correctly hang the onChange handler on <input> so that the code worked correctly, that is: rendered the necessary data, made changes to them, if necessary rendered others. Thanks for the help.

  • 2
    And why are you in inputs pushing a line, if it is assumed that there will be an array? Yes, weak typing and not such obscenities allows you to create, but there is little good in it. I did n’t study ReactJS , so I could n’t fully realize the code, but still: if you need to put only one value into the inputs , then place it as an array of one element. And if you still want to push everything into the variable, then use only the methods available to all possible objects. - Regent
  • And what exactly are you trying to do in _changeValue . I think this is nonsense. - Dmitriy Simushev

2 answers 2

Make different states for different data.

  • Try to write more detailed answers. Explain what is the basis of your statement? - Nicolas Chabanovsky
  • Not clear task. Why render inputa, when entered into which they immediately disappear, because data state is changing. Even if you make a check that the map does not go through the line, most likely all the input lines will disappear after changing one character. I think it is necessary to take one state for, another for a line. When onChange write a new state of the line and do with it what you want. - DarkSir

You should make the following changes:

 _changeValue: function (i, e) { var val = e.target.value; var newInputs = $.extend(true, [], this.state.inputs); newInputs[i] = val; this.setState({ inputs: newInputs }); }, createInput: function () { if (this.state.inputs) { return this.state.inputs.map(function (item, i) { return <input key={i} value={item} onChange={this._changeValue.bind(this, i)} /> }.bind(this)); } }, 

Note onChange={this._changeValue.bind(this, i)} . Here the index is attached to the call. And in the handler, the i parameter is already used for its intended purpose. Here I used copying an array using $.extend in order not to make changes to state directly, since it can be overwritten in parallel by another call to setState . Instead of $.extend you can use other deep copying tools if jQuery is not present in the project.