sorry bug again. im new to reactjs, i try to implement functional component and have problem with push a data inside object. i have 2 input tag and everytime i fill a value inside and switch to another the other show undefined. im not sure what is happening in here. help me explain what happen and how to solve it. please advise , thank you so much. below here i put a picture and my code.
function App() {
const [heldItems, setHeldItems] = useState({
salesno: '',
plu: '',
price: '',
dateandtime: '',
});
const [edit, setEdit] = useState({});
const [salesItemsTemp, setSalesItemsTemp] = useState([]);
const handlerOnEdit = (heldItemsData) => {
console.log(heldItemsData);
setHeldItems(heldItemsData);
setEdit(heldItemsData);
};
const handlerOnChange = (e, type) => {
setHeldItems({
[type]: e.target.value,
});
};
useEffect(() => console.log(heldItems));
const handlerOnSubmit = (e) => {
e.preventDefault();
const data = {
salesno: uniqid(),
plu: heldItems.plu,
price: heldItems.price,
dateandtime: new Date().toLocaleString(),
};
console.log(data);
};
const handlerRemove = (heldItemsSalesNo) => {
let filteredSalesItemsTemp = salesItemsTemp.filter(
(item) => {
return item.salesno !== heldItemsSalesNo;
},
);
setSalesItemsTemp(filteredSalesItemsTemp);
};
return (
<>
<form onSubmit={handlerOnSubmit} autoComplete="off">
<h1>GoGreen Point Of Sales</h1>
<input
type="text"
placeholder="Input item name"
name="plu"
onChange={(e) => handlerOnChange(e, 'plu')}
value={heldItems.plu}
/>
PLU
<input
type="number"
placeholder="Input item price"
name="price"
onChange={(e) => handlerOnChange(e, 'price')}
value={heldItems.price}
/>
Price
<button type="submit">
{edit.salesno ? 'Save Edit Item' : 'Save Item'}
</button>
<div>
<table>
<caption>Sales</caption>
<thead>
<tr>
<th>SalesNo</th>
<th>PLUName</th>
<th>Price</th>
<th>Date & Time</th>
<th>Void</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
{salesItemsTemp.map((sales) => {
const { salesno, plu, price, dateandtime } =
sales;
return (
<tr key={salesno}>
<td>{salesno}</td>
<td>{plu}</td>
<td>{price}</td>
<td>{dateandtime}</td>
<td>
<button
type="button"
onClick={() =>
handlerRemove(salesno)
}>
X
</button>
</td>
<td>
<button
type="button"
onClick={() =>
handlerOnEdit(sales)
}>
Edit
</button>
</td>
</tr>
);
})}
</tbody>
<tfoot>
<tr>
<td>brought to you by ...</td>
</tr>
</tfoot>
</table>
</div>
</form>
</>
);
CodePudding user response:
You are replacing the complete object. The following may help:
const handlerOnChange = (e, type) => {
setHeldItems((prevValue)=>({...prevValue,
[type]: e.target.value,
}));
};
CodePudding user response:
In your handlerOnChange
you're replacing the previous state with a new object which has only one property, so you've lost your previous state. To fix it use handlerOnChange
like this:
const handlerOnChange = (e, type) => {
setHeldItems(prevState => ({
...prevState,
[type]: e.target.value,
}));
};
CodePudding user response:
The issue is that inside your handlerOnChnage
method you replace the previous state, with new state and thus the previous state is lost!! Yes all those 4 types are lost and you are left with just one!!
You wanna preserve the previous state, sure? Then you can do that too..
Never Do this
You might find some solution like :const handlerOnChange = (e, type) => {
setHeldItems({
...heldItems,
[type]: e.target.value,
});
};
Since the set state is asynchronous you can't expect the state to be updated just after setHelditems
gets executed. Want more detail on it ? Visit
More clean solution
Do we have a proper solution? Yes and here it is : Use a callback function and update the state with the use of thatconst handlerOnChange = (e, type) => {
setHeldItems(prevSnapshot=>({...prenSnapshot,
[type]: e.target.value,
}));
};