Reputation: 2741
I'm solving a fun react exercise where there can be multiple input fields and changing any of them updates a sum value and I'm wondering how I can create x number of input elements using a for loop. I've created a function called createInputs that takes in a number and outputs an instance of the Input component. they come back as up [object Object][object Object][object Object, how do I fix that?
class Input extends Component {
state = {
number: ''
}
handleInput = e => {
const { value } = e.target;
const parsedValue = value !== '' ? parseFloat(value) : value;
if (parsedValue !== '') {
if (Number.isInteger(parsedValue)) {
this.setState({ number: parsedValue });
this.props.updateSum(parsedValue, this.props.index);
} else {
alert('Please enter a valid (numeric) value for Input #' + this.props.index);
}
} else {
this.setState({ number: '' });
this.props.updateSum(0, this.props.index);
}
}
render() {
return (
<div>
<span>{this.props.index}</span>
<input onChange={this.handleInput} type="text" value={this.state.number} />
</div>
)
}
}
class Sum extends Component {
state = {
sum: []
}
createInputs = count => {
let ui = '';
for (let i = 0; i < count; i++) {
ui+= <Input index={i} updateSum={this.updateSum} />
}
return ui;
}
updateSum = (e, index) => {
const _sum = this.state.sum.slice(0);
_sum[index] = e;
this.setState({
sum: _sum
})
}
render() {
const { count, sum } = this.state;
return (
<>
{
this.createInputs(this.props.count)
}
<div>
<span>Sum: {sum.length > 0 ? sum.reduce((a, v) => a += v) : 0}</span>
</div>
</>
)
}
}
class App extends Component {
render() {
return (
<Sum count={3} />
);
}
}
export default App;
Upvotes: 0
Views: 1632
Reputation: 36574
Because in for loop
you used return
. During the first loop it will return the value. Instead just them in array
and then map
over it. If you don't want wrapper <div>
you can use <React.Fragment>
createInputs = count => {
let arr = []
for (let i = 0; i < count; i++) {
arr.push(<Input index={i} updateSum={this.updateSum} />)
}
return(<div>
{arr.map(input=>input)}
</div>)
}
If you don't want to create array and then push then use
createInputs = count => {
return(<div>{Array(count).fill(1).map((input,i)=>(
<Input index={i} updateSum={this.updateSum} />))}
</div>)
}
Upvotes: 2
Reputation: 805
createInputs = count => {
for (let i = 0; i < count; i++) {
return (
<Input index={i} updateSum={this.updateSum} />
)
}
}
Your first issue here is that you will always return during the first loop. You need to accumulate your multiple inputs and return all of them AFTER you complete all the loops.
Also usually, I would use a map function inside the render to return an input for each loop.
Upvotes: 2