I am kind-of new to react and having trouble getting value of a radio button generated from a loop. I have a fiddle set-up at: https://jsfiddle.net/rexonms/zrax0zfa/.
The example has two type of radio buttons. One group is generated using loop and the other one without loop. The one without loop works (logs the value of the button) but the ones created with the loop doesn't work when I try to console log the value of the radio button.
Thank you in advance.
var Inputs = React.createClass({
getInitialState: function(){
return {
radios: {
a: { radio: 'Radio Loop A' },
b: { radio: 'Radio Loop B' },
c: { radio: 'Radio Loop C' }
},
radioNoLoop: 'Radio No Loop'
}
},
selectHandlerLoop: function(e){
console.log(e.target.value);
},
selectHandle: function(e){
console.log(e.target.value);
},
render: function() {
var radios = this.state.radios;
var r = this;
return(
<div>
{/* Creating radio buttons using Array */}
{Object.keys(radios).map(function(key,r) {
return (
<div key={key}>
<label forHTML={key}>
<input type="radio" name="loopTest" value={radios[key].radio} id={key} nChange={r.selectHandlerLoop} /> {radios[key].radio}
</label>
</div>
);
})}
<hr />
{/* Radio button no array loop */}
<label forHTML="noLoop">
<input type="radio" id="noLoop" value="noLoop" onChange={this.selectHandle}/> {this.state.radioNoLoop}
</label>
</div>
);
}
});
React.render(<Inputs />, document.getElementById('container'));
javascript map actually has functionality for what you're trying to do. you pass this
to the second argument of map (after the callback):
{Object.keys(radios).map(function(key) {
return (
<div key={key}>
<label forHTML={key}>
<input type="radio" name="loopTest" value={radios[key].radio} id={key} onChange={this.selectHandlerLoop} /> {radios[key].radio}
</label>
</div>
);
}, this)}
Your problem has nothing to do with React. You seem to have a misunderstanding of how functions / closures work.
Lets look at that part:
Object.keys(radios).map(function(key,r) { ... });
This declares a function expecting two arguments, key
and r
, and passes it to .map
. .map
will call the function and provide the corresponding arguments.
If you look at the .map
documentation you can see that .map
passes three arguments to the callback:
callback
Function that produces an element of the new Array, taking three arguments:
currentValue
: The current element being processed in the array.index
: The index of the current element being processed in the array.array
: The array map was called upon.
So what will the value of r
be? It will be the index of the current element.
The parameter r
has nothing to do with the variable r
you declared with
var r = this;
If you want r
inside the callback to refer to that variable, remove it from the parameter list
Object.keys(radios).map(function(key) { ... });
// ^ no r
r
is now a free variable inside the callback and will be looked up in higher scopes.
To learn more about closures, have a look at this MDN article.
We can simplify the mapping by using ES6 arrow functions, which you can use if you transpile your code with Babel or jsx --harmony
:
{Object.keys(radios).map(key =>
<div key={key}>
<label forHTML={key}>
<input ... nChange={this.selectHandlerLoop} /> {radios[key].radio}
</label>
</div>
)}
Because this
inside arrow functions is lexically scoped, it will refer to the this
value of the render
method, which is your React component.
来源:https://stackoverflow.com/questions/30401854/how-to-trigger-this-within-a-loop-in-react