Reputation: 944
I have my code:
function App() {
const [refundData, setRefundData] = useState(Array<ICancellationRefundOptionModel>());
const [grid, setGridData] = useState(Array<JSX.Element>());
useEffect(() => {
getFailedRequests()
}, []);
const getFailedRequests = async () => {
const failedRefundData = await getRequestAsync("myApiUrl")
setRefundData(failedRefundData);
createTable(failedRefundData);
}
const createTable = (dataArray: Array<ICancellationRefundOptionModel>) => {
const dataTable = dataArray.map(x => {
return (<tr>
<td>{x.customerId}</td>
<td><button onClick={() => handleOnClick(x)}>Process</button></td>
</tr>
)
})
setGridData(dataTable);
}
const handleOnClick = async (refund: ICancellationRefundOptionModel) => {
await postRequestAsync(refund, "");
const newGrid = refundData.filter((item) => item.customerId !== refund.customerId);
createTable(newGrid);
}
return (
<div className="App">
<Table striped bordered hover>
<thead>
<tr>
<th>Customer Id</th>
<th></th>
</tr>
</thead>
<tbody>
{grid}
</tbody>
</Table>
</div>
);
}
export default App;
This makes a call to my api where I get my data to populate a table. What I'm trying to do is after a user clicks one of the Process buttons, that customer is processed so the row will be removed from my table, but the issue is when I click on one of the buttons, the "refundData" state is empty, even though it has a value after the page loads (I put a console.log in my getFailedRequests method and it has all the data it should).
I'm not really understanding why refundData is being set to empty.
Upvotes: 0
Views: 990
Reputation: 6627
As pointed out by Drew Reese in the comment - you shouldn't be storing the grid as a state object. Instead, just render it on the fly once the refundData
has been returned.
If you simplify the component as follows, not only is it easier to understand, but it should fix up your closure problems. Note that the handleOnClick
event handler now changes the refundData
state after the click event - the net effect of this is that it will cause the table to render without the row that has been removed.
function App() {
const [refundData, setRefundData] = useState<ICancellationRefundOptionModel[]>([]);
useEffect(() => {
getFailedRequests();
}, []);
const getFailedRequests = async () => {
const failedRefundData = await getRequestAsync("myApiUrl")
setRefundData(failedRefundData);
}
const handleOnClick = async (refund: ICancellationRefundOptionModel) => {
await postRequestAsync(refund, "");
setRefundData(prev => prev.filter((item) => item.customerId !== refund.customerId));
}
return (
<div className="App">
<Table striped bordered hover>
<thead>
<tr>
<th>Customer Id</th>
<th></th>
</tr>
</thead>
<tbody>
{refundData?.length && refundData.map(x => (
<tr>
<td>{x.customerId}</td>
<td><button onClick={() => handleOnClick(x)}>Process</button></td>
</tr>
))}
</tbody>
</Table>
</div>
);
}
export default App;
Upvotes: 1