Hello people! As I mentioned, I have a component which (I don’t know why) doesn’t rerender after I send a delete request. This is the component (sorry, I had to drop it all). The delete button sends a DELETE request to the server; that part works, (I get back a 200 and item gets successfully deleted from the db).
What doesn’t work is that it does not re-render afterwards.
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import {
StyledTableCell,
StyledTableRow,
useCustomStyles,
} from "../../shared/useStyles";
import BookItemComponent from "../BookItemComponent";
import { useDispatch, useSelector } from "react-redux";
import { Fragment, useCallback, useEffect } from "react";
import { fetchInventary, removeItem } from "../../rtk/slices/inventary.slice";
import Add from "../pages/forms/addItem";
import Edit from "../pages/forms/editItem";
import Delete from "../utils/buttons/delete";
import { useHistory } from "react-router";
const InventoryTable = ({ onlyAvailable, type }) => {
const classes = useCustomStyles();
const dispatch = useDispatch();
const inventary = useSelector((state) => state.inventary);
const items = onlyAvailable
? inventary.filter((item) => item.isAvailable)
: inventary;
const initFetch = useCallback(() => {
dispatch(fetchInventary());
}, [dispatch]);
useEffect(() => {
initFetch();
}, [initFetch]);
const history = useHistory();
const handleDelete = (id) => {
alert(`This will delete the item with ID ${id} from the database`);
dispatch(removeItem(id)).then((res) => history.push("/inventario"));
};
return (
<Fragment>
{type === "manage" ? <Add /> : null}
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="last rents">
<TableHead>
<TableRow>
<StyledTableCell className={classes.rowItemId}>
I.D.
</StyledTableCell>
<StyledTableCell align="center">Modello</StyledTableCell>
<StyledTableCell align="center">Oggetto</StyledTableCell>
<StyledTableCell align="center">Disponibile</StyledTableCell>
<StyledTableCell align="center">Quantità</StyledTableCell>
<StyledTableCell></StyledTableCell>
{type === "manage" ? <StyledTableCell></StyledTableCell> : null}
</TableRow>
</TableHead>
<TableBody>
{items.map((row) => (
<StyledTableRow key={row.id}>
<StyledTableCell
component="th"
scope="row"
className={classes.rowItemId}
>
{row.id}
</StyledTableCell>
<StyledTableCell align="center">
{row.description}
</StyledTableCell>
<StyledTableCell align="center">{row.name}</StyledTableCell>
<StyledTableCell align="center">
{row.isAvailable ? "Sì" : "No"}
</StyledTableCell>
<StyledTableCell align="center">
{row.quantity !== "" ? parseInt(row.quantity, 10) : ""}
</StyledTableCell>
{type === "rental" ? ( // if type is rental render the item and modal to book an item
<StyledTableCell align="center">
<BookItemComponent
isAvailable={row.isAvailable}
item={
<div>
{row.name}, <em>{row.description}</em>
</div>
}
/>
</StyledTableCell>
) : (
// if type is not rental, render the buttons to edit and delete
<Fragment>
<StyledTableCell align="center">
<Edit rowId={row.id} description={row.description} />
</StyledTableCell>
<StyledTableCell align="center">
<Delete handleDelete={handleDelete} rowId={row.id} />
</StyledTableCell>
</Fragment>
)}
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Fragment>
);
};
export default InventoryTable;
This is the slice (if needed):
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import InventaryService from "../../services/inventary.service";
export const fetchInventary = createAsyncThunk(
"inventary/fetchInventary",
async () => {
const res = await InventaryService.getAll();
return res.data;
}
);
export const createItem = createAsyncThunk(
"inventary/createItem",
async (data) => {
const res = await InventaryService.create(data);
return res.data;
}
);
export const removeItem = createAsyncThunk(
"inventary/removeItem",
async (id) => {
const res = await InventaryService.removeOne(id);
return res.data;
}
);
const inventarySlice = createSlice({
name: "inventary",
initialState: [],
reducers: {
addItem(state, action) {
state.unshift(action.payload);
},
deleteItem(state, action) {
return state.filter((item) => item.id !== action.payload);
},
},
extraReducers: {
[fetchInventary.fulfilled]: (state, action) => {
return [...action.payload];
},
[createItem.fulfilled]: (state, action) => {
state.push(action.payload);
},
[removeItem.fulfilled]: (state, action) => {
let index = state.findIndex(({ id }) => id === action.payload.id);
state.splice(index, 1);
},
},
});
export const { addItem, deleteItem } = inventarySlice.actions;
export default inventarySlice.reducer;
My first idea is that since the component reads a copy of the state and not the state itself, it doesn’t realize that the state changed, but I still don’t really know how to fix this issue, since I need to conditionally render something or not based on a condition. Can someone please tell me how to fix this?