Reputation: 1827
I am new to ReactJS, I am trying to create 10 buttons with for loops, and set a variable with the integer from the for loop, however the function setMqty(i) always returns 11 for all the buttons. What is the correct way for doing this?
var qtyButtons = [];
for(var i = 1; i < 11; i++) {
qtyButtons.push(<div
onClick={(btn) => {qtyBtnToggle(btn);setMqty(i); }}
>
{i}
</div>)
}
Thank you in advance.
Upvotes: 1
Views: 71
Reputation: 21130
The main issue here has to do with scoping. Let me reduce your example to a more minimal example:
var qtyCallbacks = [];
for (var i = 1; i < 11; i++) {
qtyCallbacks.push(() => console.log(i));
}
for (const callback of qtyCallbacks) {
callback();
}
What's going wrong here? Why is it only logging 11
and not 1-10
?
The issue is that a variable defined with var
are scoped to the nearest function or globally if not in a function. So what does this mean?
It means that each iteration in your for loop refers to the same i
. This isn't an issue if you directly use i
.
for (var i = 1; i < 11; i++) {
console.log(i); // logs 1-10
}
However it does become an issue if you refer to i
in code that is executed at a later point. The reason the initial snippet only logs 11
is because all the callbacks are created, each one referring to the same i
. So when you evoke each callback after the for-loop is complete, they will all refer to the current value (which is 11
).
for (var i = 1; i < 11; i++) {
}
console.log(i); // logs 11
// so if we invoke the callbacks here they all log 11
So how do you solve this issue? The simplest solution is probably to replace var
with let
. let
will create a new variable for each for-iteration. Meaning that each created callback will refer to their own i
and not a shared i
. This also means that you cannot access i
outside of the for-loop.
var qtyCallbacks = [];
for (let i = 1; i < 11; i++) {
qtyCallbacks.push(() => console.log(i));
}
for (const callback of qtyCallbacks) {
callback();
}
console.log(i); // expected error, `i` is only available within the for-block
Upvotes: 1
Reputation: 311
I think using a map function is the correct way for doing it.
Therefore, you must generate a range of numbers our any element to be able to perform a map function.
So if i was in your place i would have do it like:
const [mqty, setMqty] = useState(0);
// ...
const qtyButtons = Array(10).fill().map((_, i) => {
const value = parseInt(i);
return (
<button onClick={handleClick(value)}>
{value}
</button>
);
});
// ...
// The trick here is that function returning another function, beware of that
const handleClick = (i) => () => {
setMqty(i);
};
Upvotes: 1
Reputation: 168
I am guessing setMqty is a state.Can you try
setMqty(currentValue=> currentValue+1)
Upvotes: 0