Reputation: 2033
I am having trouble in setting the values to looped elements in React.js
What I am trying to achieve is, there's a list of items:
[{ id: 1, rate: 120 } ...]
I want to create 4 text boxes: Rate, Total Cost, Advance and Balance.
Total cost is calculated using the rate and another property from the object, size (rate * size). Now, everytime rate changes, I want to calculate the total cost, and assign it to the respective row's total cost textbox. Also, on first load, the textboxes should be pre-filled with these calculated values.
array.forEach((item) => {
<div>
<input type="text" ref/id={`item_r_${item.id}`} /> // Rate
<input type="text" ref/id={`item_r_${item.id}`} /> // Total Cost
<input type="text" ref/id={`item_r_${item.id}`} /> // Advance
<input type="text" ref/id={`item_r_${item.id}`} /> // Balance
</div>
})
How can I achieve this?
I've tried using refs but couldn't get it to work.
Thanks!
Upvotes: 1
Views: 333
Reputation: 5135
I have a solution without using refs
, it updates the value of inputs
with their index.
UPDATE
Calculation of advance and balance is added in function calculateBalance
and onChangeAdv
respectively.
class App extends React.Component {
constructor() {
super();
this.state = {
data: [
{ id: 1, rate: 120, size: 3, adv: 0 },
{ id: 2, rate: 150, size: 7, adv: 0 },
{ id: 3, rate: 180, size: 5, adv: 0 }
]
};
}
onChange(e, i) {
const data = [...this.state.data];
data[i].rate = e.target.value;
data.splice(i, 1, data[i]);
this.setState({ data });
}
onChangeAdv(e, i) {
const data = [...this.state.data];
data[i].adv = e.target.value;
data.splice(i, 1, data[i]);
this.setState({ data });
}
calculateBalance(i) {
let { data } = this.state;
let bal = 0;
bal = (data[i].rate * data[i].size) - data[i].adv;
return bal;
}
render() {
let { data, adv } = this.state;
return (
<div>
{data.map((item, i) => {
return (
<div key={i}>
<input
type="text"
value={item.rate}
onChange={e => this.onChange(e, i)}
/>
// Rate
<input type="text" value={item.rate * item.size} /> // Total Cost
<input type="text" value={item.adv} onChange={e => this.onChangeAdv(e, i)} /> // Advance
<input type="text" value={this.calculateBalance(i)} /> // Balance
<br />
<br />
</div>
);
})}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Upvotes: 1