Im creating an invoice generator where the user can add an item, its price, and the quantity. I want to access the user inputs as a state from a child functional component (TableItems.js) into a parent functional component (TableSheet.js) to be able to save the user inputs into a database preferably firestore. I'm having a problem accessing the user input value from the child component to the parent component. I have been struggling with this bug for days, i really hope you guys could help me.
This is the Child component
import React, {useState, useEffect} from 'react'
function TableItems({index, tableItem }) {
const [price, setPrice] = useState(0);
const [qty, setQty] = useState(0);
const [total, setTotal] = useState([]);
useEffect(() => {
//arithmetically add price and qty values
const x = Number(price) * Number(qty)
setTotal(x)
return () => {
//clean up function will be here
};
}, [price, qty, total ]);
return (
<>
<tr>
<td><input type='text' required/></td>
<td><input type='number' value={price} onChange={(e) => setPrice(e.target.value)}/></td>
<td><input type='number' value={qty} onChange={(e) => setQty(e.target.value)}/></td>
<td>{total}</td>
</tr>
</>
)
}
export default TableItems
This is the Parent component
import React, { useState } from 'react'
import TableItems from './TableItems'
function TableSheet() {
const [tableItem, setTableItem] = useState([1]);
//adding a new table cell (table row)
const addCell = () => {
setTableItem((t) => [...t, t + 1])
}
return (
<div>
<table>
<thead>
<th>Item Description</th>
<th>Price</th>
<th>Qty.</th>
<th>Total</th>
</thead>
{
tableItem.map((tableItem, index, setItem) => {
return <TableItems key={index} tableItem={tableItem} setItem={setItem} addCell={addCell}/>
})
}
</table>
<button onClick={addCell}>+</button>
</div>
)
}
export default TableSheet
You tableItem state should contains item objects (quantity and price)
TableItems
function TableItems({ index, tableItem, onChangeItem }) {
return (
<>
<tr>
<td>
<input type="text" required />
</td>
<td>
<input
type="number"
value={tableItem.price}
onChange={(e) => onChangeItem(index, "price", e.target.value)}
/>
</td>
<td>
<input
type="number"
value={tableItem.quantity}
onChange={(e) => onChangeItem(index, "quantity", e.target.value)}
/>
</td>
<td>{Number(tableItem.price) * Number(tableItem.quantity)}</td>
</tr>
</>
);
}
TableSheet
function TableSheet() {
const [tableItem, setTableItem] = useState([
{
price: 0,
quantity: 0
}
]);
const onChangeItem = (index, type, value) => {
const newTable = tableItem.map((item, idx) => {
if (idx === index)
return {
...item,
[type]: value
};
return item;
});
setTableItem(newTable);
};
const addCell = () => {
setTableItem((t) => [
...t,
{
price: 0,
quantity: 0
}
]);
};
const totalPrice = tableItem.reduce((acc, cur) => {
acc += Number(cur.price) * Number(cur.quantity);
return acc;
}, 0);
return (
<div>
<table>
<thead>
<th>Item Description</th>
<th>Price</th>
<th>Qty.</th>
<th>Total</th>
</thead>
{tableItem.map((tableItem, index) => {
return (
<TableItems
key={index}
index={index}
tableItem={tableItem}
onChangeItem={onChangeItem}
/>
);
})}
</table>
<button onClick={addCell}>+</button>
<div>Total: {totalPrice}</div>
</div>
);
}
you can check in my codesandbox. Hope it help!