I'm trying to use a custom react hook to create a counter for each item in a list. the problem is when I increase or decrease a counter, the value of other counters change simultaneously. basically all of the counters show the same value. here is my custom hook:
import { useState } from "react";
export const useQuantity = (defaultQuantity) => {
const [value, setValue] = useState(defaultQuantity || 1);
const onChange = (e) => {
if (!+e.target.value >= 1) {
setValue(1);
return;
}
setValue(+e.target.value);
};
return {
value,
setValue,
onChange,
};
};
how can I change the value of a counter while it doesn't effect the other counters?
This is the ponent that I map through the items and for each one of them I render the QuantityInput ponent.
import { useQuantity } from "../Hook/useQuantity";
import { QuantityInput } from "./QuantityInput";
export const Order = () => {
const quantity = useQuantity();
return (
orders.map((order) => (
<QuantityInput quantity={quantity} />
)
)
}
and this is QuantityInput ponent:
export const QuantityInput = ({ quantity }) => {
const decrement = () => {
quantity.setValue(quantity.value - 1);
};
const increment = () => {
quantity.setValue(quantity.value + 1);
};
return (
<Button
onClick={decrement}
disabled={quantity.value === 1}
>
-
</Button>
<Input {...quantity} />
<Button onClick={increment}> + </Button>
);
};
I'm trying to use a custom react hook to create a counter for each item in a list. the problem is when I increase or decrease a counter, the value of other counters change simultaneously. basically all of the counters show the same value. here is my custom hook:
import { useState } from "react";
export const useQuantity = (defaultQuantity) => {
const [value, setValue] = useState(defaultQuantity || 1);
const onChange = (e) => {
if (!+e.target.value >= 1) {
setValue(1);
return;
}
setValue(+e.target.value);
};
return {
value,
setValue,
onChange,
};
};
how can I change the value of a counter while it doesn't effect the other counters?
This is the ponent that I map through the items and for each one of them I render the QuantityInput ponent.
import { useQuantity } from "../Hook/useQuantity";
import { QuantityInput } from "./QuantityInput";
export const Order = () => {
const quantity = useQuantity();
return (
orders.map((order) => (
<QuantityInput quantity={quantity} />
)
)
}
and this is QuantityInput ponent:
export const QuantityInput = ({ quantity }) => {
const decrement = () => {
quantity.setValue(quantity.value - 1);
};
const increment = () => {
quantity.setValue(quantity.value + 1);
};
return (
<Button
onClick={decrement}
disabled={quantity.value === 1}
>
-
</Button>
<Input {...quantity} />
<Button onClick={increment}> + </Button>
);
};
Share
Improve this question
edited Apr 27, 2020 at 11:30
OmidJr
asked Apr 27, 2020 at 11:13
OmidJrOmidJr
1334 silver badges8 bronze badges
3
- Hi @OmidJr, please: format your code, and post the Component where you get the issue – leonardfactory Commented Apr 27, 2020 at 11:16
- as far as I can see now you only have one counter state can you please explain more what is happening with a single number how are you supposed to keep track of 3 counters? – nikoss Commented Apr 27, 2020 at 11:17
- @leonardfactory I reformatted the code, you can check it out. – OmidJr Commented Apr 27, 2020 at 11:34
2 Answers
Reset to default 5Instead of useQuantity
in your parent ponent, you should use it in QuantityInput
ponent so each of them hold their state.
export const QuantityInput = () => {
const quantity = useQuantity(); // Use quantity here, do not need to pass from props
const decrement = () => {
quantity.setValue(quantity.value - 1);
};
const increment = () => {
quantity.setValue(quantity.value + 1);
};
return (
<Button
onClick={decrement}
disabled={quantity.value === 1}
>
-
</Button>
<Input {...quantity} />
<Button onClick={increment}> + </Button>
);
};
The hook that you implemented holds one state value and will only suffice for it.
The solution here is to implement a ponent that uses this hook. Once you have the ponent you can render as many instances of it as you want
Also you could simply implement a ponent instead of custom hook
import { useState } from "react";
export const QuantityInput = (props) => {
const [value, setValue] = useState(props.defaultQuantity || 1);
const onChange = (e) => {
if (!+e.target.value >= 1) {
setValue(1);
return;
}
setValue(+e.target.value);
};
return (
<div>
<div>{value}</div>
<input value={value} onChange={onChange} />
</div>
)
};
const Parent = ({arr}) => {
return arr.map(item => <QuantityInput defaultQuantity={item.defaultQuantity} />)
}