Home > Software engineering >  i try to push a value inside an object and its always show undefined everytime i switch to another i
i try to push a value inside an object and its always show undefined everytime i switch to another i

Time:12-08

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.

my issue

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 that
const handlerOnChange = (e, type) => {
  setHeldItems(prevSnapshot=>({...prenSnapshot,
    [type]: e.target.value,
  }));
};

Helpful link

  • Related