My expected output:
- Only show the
textfieldcolorswhen thebuttonadd coloris cliked. - Only one textfield shows when clicking the
buttonadd coloris clicked initially then adding more textfields in the next clicked and also be able to remove a specific color.
What is currently happening and my problem:
- When the page initially renders, the
removebutton is shown. In which, it should not be. It must only be shown when a textfieldcolorappears. - Clicking the button
add colordoes make the textfieldcolorappear. However, instead of just onetextfield, it displays 2textfields. - Also, if I remove all of the
textfieldI added, theAdd colorbuttondisappears, hence, removing all of the textfields does not allow me to add more of it. In which it should not. Even removing all of thetextfields, I should still be able to add more colors.
How would I fix this? Am I doing something wrong with the conditionals for the buttons? Any help would be appreciated. Thank you.
The codes:
const [addColor, setAddColor] = useState(false);
const [colorList, setColorList] = useState([{ color: "", colorStocks: "" }]);
//for the colors
const handleColorChange = (e, index) => {
const { name, value } = e.target;
setColorList((prevState) => {
const list = [...prevState];
list[index][name] = name === "colorStocks" ? +value : value;
return list;
});
};
const handleColorRemove = (index) => {
const list = [...colorList];
list.splice(index, 1);
setColorList(list);
};
const handleColorAdd = () => {
setAddColor(true);
setColorList([...colorList, { color: "", colorStocks: "" }]);
};
{colorList.map((singleColor, index) => (
<div key={index}>
<div style={{ display: "flex" }}>
<>
{addColor === true && (
<>
<Grid
item
xs={6}
style={{ display: "inline-block" }}
>
<TextField
label="Color"
name="color"
type="text"
id="color"
required
value={singleColor.color}
onChange={(e) => handleColorChange(e, index)}
/>
</Grid>
<br />
<Grid
item
xs={6}
style={{ display: "inline-block" }}
>
<TextField
label="Stocks"
name="colorStocks"
type="number"
id="colorStocks"
required
value={singleColor.colorStocks}
onChange={(e) => handleColorChange(e, index)}
/>
</Grid>
</>
)}
</>
</div>
<br />
<Grid item xs>
{colorList.length >= 1 && (
<Button
color="secondary"
onClick={() => handleColorRemove(index)}
>
Remove
</Button>
)}
</Grid>
<br />
{colorList.length - 1 === index && (
<Button
onClick={handleColorAdd}
variant="outlined"
color="primary"
fullWidth
>
Add Color
</Button>
)}
{(colorList.length, "- colorList")}
<br />
{(index, "-index")}
</div>
))}
>Solution :
multiple issues in your code:
When the page initially renders, the remove button is shown. In which,
it should not be. It must only be shown when a textfield color
appears.
colorList when you initiate your component is equal to:
[{ color: "", colorStocks: "" }]
which length === 1 (one object with two keys and two empty string values)
so the condition:
colorList.length >= 1
will be true at initial render. Initiate with an empty array rather:
const [colorList, setColorList] = useState([]);
Clicking the button addcolor does make the textfield color appear.
However, instead of just one textfield, it displays 2 textfields.
Your function handleColorAdd changes addColor to true which is good to show the component. However same issue as before: Your original array already has an empty color and you add a second one on top of it, which makes two objects in your colorList:
setColorList([...colorList, { color: "", colorStocks: "" }]);
Once again, starting with an empty array will resolve this issue.
Also, if I remove all of the textfield I added, the Add color button
disappears, hence, removing all of the textfields does not allow me to
add more of it. In which it should not. Even removing all of the
textfields, I should still be able to add more colors.
Your addColor button is part of the map on ColorList. Indeed if colorList becomes an empty array nothing will display anymore. Best solution is to take out the addColor button from this map function.