I am trying to get value from the radio button the problem is I can get the values but when I tried to store on my state it only updates 2 times after the 3rd time when I try to update the state it is not updating.
Radio buttons code.
<li> <label className="container_radio"> Small <span>+ $5</span> <input type="radio" required onChange={(e) => handleChange(e, product)} defaultValue={5} name={"size"} /> <span className="checkmark"></span> </label> <label className="container_radio"> Medium <span>+ $10</span> <input type="radio" required onChange={(e) => handleChange(e, product)} defaultValue={10} name={"size"} /> <span className="checkmark"></span> </label> <label className="container_radio"> Large <span>+ $15</span> <input type="radio" required onChange={(e) => handleChange(e, product)} defaultValue={15} name={"size"} /> <span className="checkmark"></span> </label> </li>
I am trying to achieve output something like this
[{title: 'Barnes Chapman', options:{Medium size: '5.00' } }]
My ui:
My function: problem is here if (isExist) { isExist.options = { ...isExist.options, [name]: value, }; return prevValue;
for this code the state is not updaing unlimited time.
const handleChange = (e, product) => { // Destructuring const { name, value, checked } = e.target; console.log(`${value} is ${checked} `); // Case 1 : The user checks the box if (checked) { setProductInfo((prevValue) => { const isExist = prevValue.find((item) => item.title === product.title); if (isExist) { isExist.options = { ...isExist.options, [name]: value, }; return prevValue; } else { return [ ...prevValue, { title: product.title, options: { [name]: value }, }, ]; } }); } // Case 2 : The user unchecks the box else { setProductInfo(productinfo.filter((e) => e.title !== name)); } };
Advertisement
Answer
There are few problems in your code.
1. Don’t change state variable directly.
In the following code, you are trying to change state
variable directly. This may result unexpected result.
const isExist = prevValue.find((item) => item.title === product.title); if (isExist) { isExist.options = { ...isExist.options, [name]: value, }; return prevValue; }
You can read more about it.
Why can’t I directly modify a component’s state
2. In this code, you should compare array item by title
instead of name
.
Because you are using title
.
// Case 2 : The user unchecks the box else { setProductInfo(productinfo.filter((e) => e.title !== name)); }
3. Updated code based on your code in codesandbox
import { useState } from "react"; import Select from "react-select"; import "./styles.css"; export default function App() { const [productinfo, setProductInfo] = useState([]); const handleChange = (e, product) => { // Destructuring const { name, value, checked } = e.target; console.log(`${value} is ${checked} ${product.title}`); // Case 1 : The user checks the box if (checked) { setProductInfo((prevValue) => { const newValue = prevValue ? [...prevValue] : []; const isExist = newValue.find((item) => item.title === product.title); if (isExist) { isExist.options = { ...isExist.options, [name]: value, }; return newValue; } else { return [ ...newValue, { title: product.title, options: { [name]: value }, }, ]; } }); } // Case 2 : The user unchecks the box else { setProductInfo(productinfo.filter((e) => e.title !== product.title)); } }; console.log(productinfo, "state"); return ( <div className="App"> <ul className="clearfix"> {/* {product.options.map((option, i) => { return ( */} <li> <label className="container_radio"> Small <span>+ $5</span> <input type="radio" required onChange={(e) => handleChange(e, { title: "title" })} defaultValue={5} name={"size"} /> <span className="checkmark"></span> </label> <label className="container_radio"> Medium <span>+ $10</span> <input type="radio" required onChange={(e) => handleChange(e, { title: "title" })} defaultValue={10} name={"size"} /> <span className="checkmark"></span> </label> <label className="container_radio"> Large <span>+ $15</span> <input type="radio" required onChange={(e) => handleChange(e, { title: "title" })} defaultValue={15} name={"size"} /> <span className="checkmark"></span> </label> </li> {/* ); */} {/* // })} */} </ul> </div> ); }