My fetch command doesn't work, what did i do wrong? - reactjs

im trying to fetch customers and trainings by using a fetch request but for some reason it doesn´t print anything in the page. However it is printing those informations in the network console.
import React, { useState, useEffect } from "react";
import Snackbar from '#material-ui/core/Snackbar';
import Addcustomer from "./Addcustomer";
import Addtraining from "./Addtraining";
import Editcustomer from "./Editcustomer";
import { AgGridReact } from'ag-grid-react'
import'ag-grid-community/dist/styles/ag-grid.css'
import'ag-grid-community/dist/styles/ag-theme-material.css';
export default function Customerlist() {
const [customers, setCustomers] = useState([]);
useEffect(() => fetchData(), []);
const fetchData = () => {
fetch('https://customerrest.herokuapp.com/api/customers')
.then(response => response.json())
.then(data => setCustomers(data.content));
};
const deleteCustomer = link => {
if (window.confirm("Are you sure to delete customer?")) {
console.log(link);
fetch(link, { method: "DELETE" })
.then(res => {
fetchData();
if (res.status >= 200 && res.status < 300) {
Snackbar({ message: "Customer deleted successfully" });
} else {
Snackbar({ message: "Error. Try again." });
}
})
.catch(err => console.error(err));
}
};
const saveCustomer = customer => {
fetch('https://customerrest.herokuapp.com/api/customers', {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(customer)
})
.then(res => {
fetchData();
if (res.status >= 200 && res.status < 300) {
Snackbar({ message: "Customer added successfully" });
} else {
Snackbar({ message: "Error. Try again." });
}
})
.catch(err => console.error(err));
};
const saveTraining = training => {
fetch('https://customerrest.herokuapp.com/api/trainings', {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(training)
})
.then(res => {
fetchData();
if (res.status >= 200 && res.status < 300) {
Snackbar({ message: "Training added successfully" });
} else {
Snackbar({ message: "Error. Try again." });
}
})
.catch(err => console.error(err));
};
const updateCustomer = (customer, link) => {
fetch(link, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(customer)
})
.then(res => fetchData())
.then(Snackbar({ message: "Customer updated successfully" }))
.catch(err => console.error(err));
};
const columns = [
{
title: "Edit",
field: "links[0].href",
render: customerData => (
<Editcustomer updateCustomer={updateCustomer} customer={customerData} />
),
sorting: false
},
{
Header: "First name",
accessor: "firstname"
},
{
Header: "Last name",
accessor: "lastname"
},
{
Header: "Email",
accessor: "email"
},
{
Header: "Phone",
accessor: "phone"
},
{
Header: "Address",
accessor: "streetaddress"
},
{
Header: "Postcode",
accessor: "postcode"
},
{
Header: "City",
accessor: "city"
},
{
title: "Delete",
field: "links[0].href",
render: customerData => (
<button
style={{ cursor: "pointer" }}
onClick={() => deleteCustomer(customerData.links[0].href)}
>Delete</button>
),
sorting: false
},
{
title: "Add training",
render: trainingRow => (
<Addtraining
saveTraining={saveTraining}
customerId={trainingRow.links[0].href}
/>
),
sorting: false
}
];
return (
<div>
<Addcustomer saveCustomer={saveCustomer} />
<AgGridReact
title="Customers"
rowData={customers}
columns={columns}
options={{ sorting: true }}
></AgGridReact>
</div>
);
}
i have multiple fetch requests for training and customers but its not working
it shows the information in the console but it doesn't show them in the page. I would like to see all the information in my page, so what i have to do or what did i do wrong here?

The props passed to AgGridReact component are not the right type.
columnDefs prop is used to declare the column headers and should look like:
const columnDefs = [
{ headerName: 'Customers',
children: [
{
headerName: 'Edit',
valueGetter: (params) => params.data.links[0].href,
cellRenderer: (params) => <Editcustomer updateCustomer={updateCustomer} customer={params.data} />,
sortable: false,
},
{
headerName: 'First name',
field: 'firstname',
},
{
headerName: 'Last name',
field: 'lastname',
},
{
headerName: 'Email',
field: 'email',
},
{
headerName: 'Phone',
field: 'phone',
},
{
headerName: 'Address',
field: 'streetaddress',
},
{
headerName: 'Postcode',
field: 'postcode',
},
{
headerName: 'City',
field: 'city',
},
{
headerName: 'Delete',
valueGetter: (params) => params.data.links[0].href,
cellRenderer: (params) => (
<button style={{ cursor: 'pointer' }} onClick={() => deleteCustomer(params.data.links[0].href)}>
Delete
</button>
),
sortable: false,
},
{
headerName: 'Add training',
valueGetter: (params) => params.data.links[0].href,
cellRenderer: (params) => (
<Addtraining
saveTraining={saveTraining}
customerId={params.data.links[0].href}
/>
),
sortable: false,
},
]
}];
defaultColDef prop is used to declare defaults for the column headers.
const defaultColDef={ sortable: true }
Your implementation of the AgGridReact element should be:
<AgGridReact
rowData={customers}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
></AgGridReact>
Finally, you need to either set the domLayout prop so that the grid size is autocomputed (ideally for very small datasets).
<AgGridReact
rowData={customers}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
domLayout='autoHeight'
></AgGridReact>
Otherwise, you can set the size of the container element so that the grid size is computed from it.
<div
style={{
height: '500px',
width: '600px',
}}
>
<AgGridReact
rowData={customers}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
></AgGridReact>
</div>

you need to conditionaly render the information when the data is ready and you need to map on every object
const [customers, setCustomers] = useState([]);
useEffect(() => fetchData(), []);
return (
<>
{customers && customers.map((obj, i) => (
<div key={i}>
<p>{obj.firstname}</p>
<p>{obj.lastname}</p>
</div>
)}
</>
)
your displaying data is more complicated because you use other components "Addcustomer", "AgGridReact" but im just showing how to basically get the data into html

Related

MUI datagrid view mode not persisting

I'm implementing a MUI datagrid with inline editing. Whenever a cell loses focus, the code sets the mode to 'view' (as it should) but then immediately the processRowUpdate callback is called (to send data to the endpoint) it sets the cell mode back to 'edit' meaning that the cell remains in edit mode.
Does anyone know why this is happening?
Maybe something to do with this processRowUpdate error logged to console?:
TypeError: Cannot read properties of undefined (reading 'id')
at getRowId (productTable.js:213:1)
at getRowIdFromRowModel (gridRowsUtils.js:17:1)
at useGridRows.js:106:1
at Array.forEach (<anonymous>)
at Object.updateRows (useGridRows.js:105:1)
at apiRef.current.<computed> [as updateRows] (useGridApiMethod.js:14:1)
at useGridCellEditing.new.js:334:1
Code:
export default function FullFeaturedCrudGrid(props) {
const [rows, setRows] = React.useState([]);
const [cellModesModel, setCellModesModel] = React.useState({})
const [selectedCellParams, setSelectedCellParams] = React.useState(null);
const { tableName } = props
const [snackbar, setSnackbar] = React.useState(null);
const handleCloseSnackbar = () => setSnackbar(null);
React.useEffect(() => {
console.log('useEffect called')
axios.get(`http://localhost:8000/mvhr/all`)
.then((response) => {
setRows(response.data);
})
}, [])
React.useEffect(() => {
console.log('cellModesModel',cellModesModel)
});
const handleCellFocus = React.useCallback((event) => {
const row = event.currentTarget.parentElement;
const id = row.dataset.id;
const field = event.currentTarget.dataset.field;
setSelectedCellParams({ id, field });
}, []);
const handleDeleteClick = (id) => () => {
axios.delete(`http://localhost:8000/delete_mvhr/${id}`
).then(() => {
setRows(rows.filter((row) => row.id !== id));
setSnackbar({ children: tableName + ' successfully deleted', severity: 'success' });
})
};
const handleCancel = () => {
if (!selectedCellParams) {
return;
}
const { id, field } = selectedCellParams;
setCellModesModel({
...cellModesModel,
[id]: {
...cellModesModel[id],
[field]: { mode: GridCellModes.View },
},
});
};
const processRowUpdate = React.useCallback(
(newRow) => {
axios.put(`http://localhost:8000/mvhr/`, newRow)
.then((response) => {
const updatedRow = { ...newRow, isNew: false };
setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row)));
setSnackbar({ children: tableName + ' successfully saved', severity: 'success' });
return updatedRow
})
});
const handleProcessRowUpdateError = React.useCallback((error) => {
setSnackbar({ children: error.message, severity: 'error' });
}, []);
const columns = [
{ field: 'description', headerName: 'description', width: 180, editable: true },
{ field: 'elec_efficiency', headerName: 'elec_efficiency', type: 'number', editable: true },
{ field: 'heat_recovery_eff', headerName: 'heat_recovery_eff', type: 'number', editable: true },
{ field: 'range_low', headerName: 'range_low', type: 'number', editable: true },
{ field: 'range_high', headerName: 'range_high', type: 'number', editable: true },
{ field: 'superseded', headerName: 'superseded', type: 'boolean', editable: true },
{
field: 'actions',
type: 'actions',
headerName: 'Actions',
width: 100,
cellClassName: 'actions',
getActions: ({ id }) => {
return [
<GridActionsCellItem
icon={<DeleteIcon />}
label="Delete"
onClick={handleDeleteClick(id)}
color="inherit"
/>,
];
},
},
];
return (
<Box
sx={{
height: '100vh',
width: '100%',
'& .actions': {
color: 'text.secondary',
},
'& .textPrimary': {
color: 'text.primary',
},
}}
>
<StripedDataGrid
rows={rows}
columns={columns}
processRowUpdate={processRowUpdate}
onProcessRowUpdateError={handleProcessRowUpdateError}
onCellEditStop={handleCancel}
cellModesModel={cellModesModel}
onCellModesModelChange={(model) => setCellModesModel(model)}
components={{
Toolbar: AddToolbar,
}}
componentsProps={{
toolbar: { setRows, setSnackbar, tableName },
cell: {
onFocus: handleCellFocus,
},
}}
experimentalFeatures={{ newEditingApi: true }}
getRowClassName={(params) =>
params.indexRelativeToCurrentPage % 2 === 0 ? 'even' : 'odd'
}
/>
{!!snackbar && (
<Snackbar
open
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
onClose={handleCloseSnackbar}
autoHideDuration={6000}
>
<Alert {...snackbar} onClose={handleCloseSnackbar} />
</Snackbar>
)}
</Box>
);
}
Solved it. I refactored the code to return the updatedRow synchronously rather than as a callback to the axios request:
const processRowUpdate = React.useCallback(
(newRow) => {
const updatedRow = { ...newRow, isNew: false };
setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row)));
setSnackbar({ children: tableName + ' successfully saved', severity: 'success' });
axios.put(`http://localhost:8000/mvhr/`, newRow)
return updatedRow
});

Data is not showing in Grid Lookup React.js MaterialUI

I need to show my lookup like this
Lookup image what I want
So the code for this lookup is which is shown is hardcoded but i want to do retrieve data dynamically.
Hardcoded data
I had done with to retrieve data from database and the data is also in same format when i console log the both they are same.
AvaibleMechanic is which we retrieve from DB and dyanmicMechanicLookUp is harcoded
Both data console log SS
setColumnsCode
const [columns, setColumns] = useState([
{ title: "OrderId", field: "_id", editable: "never" },
{ title: "Customer Name", field: "customerName", editable: "never" },
{ title: "Car Name", field: "carName", editable: "never" },
{ title: "Car Number", field: "carNumber", editable: "never" },
{ title: "Address", field: "custAddress", editable: "never" },
{ title: "Service Name", field: "serviceName", editable: "never" },
{ title: "Price", field: "servicePrice", editable: "never" },
{
title: "Assign Mechanic",
field: "mechanicId",
lookup: AvailableMechanic,
},
]);
when i want to see data which is retrieve from Database is not show on the lookup is look like this
Retrieve from database lookup SS
You can see when I used dynamicLookUp which is hardcoded it works fine but when i used data which is retrieve it's not shown on the grid
FullCode
import React, { useState, useEffect } from "react";
import AdminOrders from "../../../services/member/orders.js/admin_orders";
import MechanicService from "../../../services/member/Mechanic/Mechanic_Services";
import "./CSS/Cars.css";
import MaterialTable from "material-table";
import { useSnackbar } from "notistack";
function Orders() {
const [orders, setOrders] = useState([]);
const [completedOrders, setCompletedOrders] = useState([]);
const [AvailableMechanic, setAvailableMechanic] = useState({});
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
//for error handling
const [iserror, setIserror] = useState(false);
const [errorMessages, setErrorMessages] = useState([]);
const getAvailableMechanics = async () => {
await MechanicService.findAvailable()
.then((res) => {
res.map((key,i) => {
setAvailableMechanic(prevState => ({
...prevState,
[key._id]: key.name
}))
})
})
.catch((err) => {
console.log(err)
})
}
const getPlacedOrders = () => {
AdminOrders.findPlacedOrders()
.then((response) => {
setOrders(response);
})
.catch((err) => {
console.log(err);
});
};
const getCompletedOrders = () => {
AdminOrders.findCompletedOrders()
.then((res) => {
setCompletedOrders(res);
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
getAvailableMechanics();
getPlacedOrders();
getCompletedOrders();
}, []);
const dynamicMechanicsLookUp = {
'621d06355e364ae391f59af4': "John Doe 1",
'621e3fb9d99ae5efd754b5d6': "John Doe 2",
'62766409db9ad573da5655cc': "John Doe 3",
'6276642cdb9ad573da5655d1': "John Doe 4",
'62766433db9ad573da5655d4': "John Doe 5",
};
// const dynamicMechanicsLookUp = AvailableMechanic;
console.log("dynamicLookUp",dynamicMechanicsLookUp)
console.log("AvailableMechanic",AvailableMechanic)
const [columns, setColumns] = useState([
{ title: "OrderId", field: "_id", editable: "never" },
{ title: "Customer Name", field: "customerName", editable: "never" },
{ title: "Car Name", field: "carName", editable: "never" },
{ title: "Car Number", field: "carNumber", editable: "never" },
{ title: "Address", field: "custAddress", editable: "never" },
{ title: "Service Name", field: "serviceName", editable: "never" },
{ title: "Price", field: "servicePrice", editable: "never" },
{
title: "Assign Mechanic",
field: "mechanicId",
lookup: AvailableMechanic,
},
]);
const [column, setColumn] = useState([
{ title: "OrderId", field: "_id" },
{ title: "Customer Name", field: "customerName" },
{ title: "Car Name", field: "carName" },
{ title: "Car Number", field: "carNumber" },
{ title: "Address", field: "custAddress" },
{ title: "Service Name", field: "serviceName" },
{ title: "Price", field: "servicePrice" },
{ title: "Assigned Mechanic", field: "mechanicId" },
]);
const handleRowUpdate = (newData, oldData, resolve) => {
let errorList = [];
if (errorList.length < 1) {
AdminOrders.assignOrder(newData._id, newData.mechanicId)
.then((res) => {
const dataUpdate = [...orders];
const index = oldData.tableData.id;
dataUpdate[index] = newData;
setOrders([...dataUpdate]);
resolve();
setIserror(false);
setErrorMessages([]);
enqueueSnackbar(res, {
variant: "success",
});
})
.catch((error) => {
setErrorMessages(["Update failed! Server error"]);
setIserror(true);
resolve();
});
} else {
setErrorMessages(errorList);
setIserror(true);
resolve();
}
};
const [display, setdisplay] = useState(false);
const openTable = () => {
setdisplay(true);
};
const closeTable = () => {
setdisplay(false);
};
return (
<div className="cars_container">
<br />
<button onClick={openTable}>See Completed Orders</button>
<br />
{orders ? (
<MaterialTable
title="CURRENT ORDERS DATA"
columns={columns}
data={orders}
editable={{
onRowUpdate: (newData, oldData) =>
new Promise((resolve, reject) => {
handleRowUpdate(newData, oldData, resolve);
}),
}}
options={{
headerStyle: {
backgroundColor: "#01579b",
color: "#FFF",
},
exportButton: true,
}}
/>
) : (
<div>
<br />
<h2>NO CURRENT ORDERS RIGHT NOW</h2>
</div>
)}
<br />
<br />
<br />
{display ? (
<div>
<h1>COMPLETED ORDERS</h1>
<MaterialTable
title="CURRENT ORDERS DATA"
columns={column}
data={completedOrders}
options={{
headerStyle: {
backgroundColor: "#01579b",
color: "#FFF",
},
exportButton: true,
}}
/>
<br />
<button onClick={closeTable}>Close Table</button>
<br />
<br />
<br />
</div>
) : null}
</div>
);
}
export default Orders;
Sorry for the bad english. Please if you find any mistake i am making please let me know
Thanks

While typing in input field for filtering in material table gets disappeared

This is an example table where I am using the same remote data concept in my code, I have also tried debounce interval prop but still while typing values in the filter, it renders and text won't stay in the filtering box.
function RemoteData() {
return (
<MaterialTable
title="Remote Data Preview"
columns={[
{
title: 'Avatar',
field: 'avatar',
render: rowData => (
<img
style={{ height: 36, borderRadius: '50%' }}
src={rowData.avatar}
/>
),
},
{ title: 'Id', field: 'id' },
{ title: 'First Name', field: 'first_name' },
{ title: 'Last Name', field: 'last_name' },
]}
data={query =>
new Promise((resolve, reject) => {
let url = 'https://reqres.in/api/users?'
url += 'per_page=' + query.pageSize
url += '&page=' + (query.page + 1)
fetch(url)
.then(response => response.json())
.then(result => {
resolve({
data: result.data,
page: result.page - 1,
totalCount: result.total,
})
})
})
}
/>
)
}
Can someone please help me with how to make the text stay up in the filter input field itself without making it re-render?

If Statement Inside Map

I currently have a DataGrid that is rendering data grabbed from my backend mongoDB. The data rendering is mapped to keys specified by the objects in the mongoDB document. In each document is a set of boolean values, and I am trying to check if any of those are true, if they are true it will render a Y in the repairsNeeded column for each row, if not, it will render an N. The main problem I am running into is where/how to check this. I have played with a few different ideas to no avail. Right now I have the repairsNeeded column for each row assigned to the document.isPowerCordDamaged (one of my booleans), which renders true or false depending on if its checked.
Code:
function Rounding() {
const [cartsRounded, setCartsRounded] = useState([]);
let navigate = useNavigate();
useEffect(() => {
userCartsRounded()
.then((response) => {
setCartsRounded(response.data);
})
.catch((err) => {
console.log(err);
});
}, []);
const columns = [
{
field: "serialNum",
headerName: "Cart Serial Number",
width: 250,
},
{
field: "pcNum",
headerName: "Workstation Number",
width: 250,
},
{
field: "dateLastRounded",
headerName: "Last Rounded On",
width: 250,
},
{
field: "repairsNeeded",
headerName: "Repairs?",
width: 100,
},
{
field: "quarter",
headerName: "Quarter",
width: 75,
},
];
const [sortModel, setSortModel] = React.useState([
{
field: "dateLastRounded",
sort: "desc",
},
]);
const rows = useMemo(
() =>
cartsRounded.map((row, index) => ({
...row,
id: index,
serialNum: row.cartSerialNumber,
pcNum: row.pcNumber,
dateLastRounded: moment(row.updatedAt).format("MM-D-YYYY"),
repairsNeeded: row.isPowerCordDamaged,
quarter: moment(row.updatedAt).format("Qo"),
})),
[cartsRounded]
);
return (
<div>
<IconButton
color="primary"
aria-label="new rounding"
component="span"
onClick={() => {
navigate("add_new_cart");
}}
>
<AddCircleOutline />
</IconButton>
<div style={{ height: 400, width: "100%" }}>
<DataGrid
component={Paper}
rows={rows}
columns={columns}
sortModel={sortModel}
pageSize={100}
rowsPerPageOptions={[100]}
/>
</div>
</div>
);
}
export default Rounding;
Document Example:
{
_id: new ObjectId("61b95e447aec51d938e856cc"),
cartSerialNumber: 'testytitit',
pcNumber: '14124f0sdf0sfs',
isPowerCordDamaged: false,
isFuseBlown: false,
isInverterBad: false,
isInterfaceDamaged: false,
isPhysicalDamage: false,
otherNotes: '',
roundedBy: '6186c13beb18d33d5088f7b2',
createdAt: 2021-12-15T03:17:24.495Z,
updatedAt: 2021-12-15T03:17:24.495Z,
__v: 0
}
I may not be understanding the question here. But I think what you are trying to do is have the repairsNeeded field have a Y or N rather than its boolean value.
Try this.
const rows = useMemo(
() =>
cartsRounded.map((row, index) => ({
...row,
id: index,
serialNum: row.cartSerialNumber,
pcNum: row.pcNumber,
dateLastRounded: moment(row.updatedAt).format("MM-D-YYYY"),
repairsNeeded: row.isPowerCordDamaged ? "Y" : "N" // short hand for if (row.isPowerCordDamaged === true) return "Y" else return "N",
quarter: moment(row.updatedAt).format("Qo"),
})),
[cartsRounded]
);
After looking it may be you want to return Y or N if any are true? In that case best pull it into a function.
const isRepairNeeded = (row) => {
if (row.isPowerCordDamaged) return "Y";
if (row.isFuseBlown) return "Y";
... rest of the ifs
return "N"; // N is only returned if none of the if statements === true;
}
const rows = useMemo(
() =>
cartsRounded.map((row, index) => ({
...row,
id: index,
serialNum: row.cartSerialNumber,
pcNum: row.pcNumber,
dateLastRounded: moment(row.updatedAt).format("MM-D-YYYY"),
repairsNeeded: isRepairNeeded(row) // call the function will return "Y" or "N",
quarter: moment(row.updatedAt).format("Qo"),
})),
[cartsRounded]
);

Add new row with a key press like 'enter'

I would like to add a key listener with 'enter' key to "onRowAdd" action from material-table on react,
Could be able to call the function outside the table props and add a normal js listener to key enter for launch the function?
So i searched on the doc of material-table and nothing similar can help me, anyone have some idea how i can fix it?
thanks
import React, { useEffect, useState } from 'react'
import MaterialTable from 'material-table'
import axios from 'axios'
var emitter = require('../config/global_emitter')
export default function MaterialTableDemo(props) {
const [state, setState] = useState({
columns: [
{ title: 'Item', field: 'item' },
{ title: 'Quantity', field: 'quantity', type: 'numeric' },
{ title: 'Description', field: 'description' },
{ title: 'Price', field: 'price', type: 'numeric' },
{
title: 'Location',
field: 'location',
lookup: { 34: 'Batman', 63: 'Back Store' },
},
],
data: []
});
useEffect(() => {
setState({...state, data:[]})
const user = {
name: props.userSelected
}
axios.post('api', user)
.then(e => {
if (e.data !== ''){
setState({...state, data: e.data})
}
})
},[props.userSelected])
const handleUpdate = (data) => {
const upload = {
items: data,
name: props.userSelected
}
axios.post('api', upload)
.then((e) => {
if (e.status === 200){
emitter.emit('confirmMessage', 'Updated list correctly')
}
})
}
return (
<MaterialTable
title={props.userSelected + '´s items ordered'}
columns={state.columns}
data={state.data}
options={{
headerStyle: {
backgroundColor: '#01579b',
color: '#FFF'
},
rowStyle: {
opacity: 1,
animationName: 'fadeInOpacity',
animationIterationCount: 1,
animationTimingFunction: 'ease-in',
animationDuration: '2s'
}
}}
onKeyDown={(ev) => {
console.log(`Pressed keyCode ${ev.key}`);
if (ev.key === 'Enter') {
// Do code here
ev.preventDefault();
}
}}
editable={{
onRowAdd: newData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
addRow(newData)
}, 600);
}),
onRowUpdate: (newData, oldData) =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const data = [...state.data];
data[data.indexOf(oldData)] = newData;
handleUpdate(data)
setState({ ...state, data });
}, 600);
}),
onRowDelete: oldData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
const data = [...state.data];
data.splice(data.indexOf(oldData), 1);
handleUpdate(data)
setState({ ...state, data });
}, 600);
}),
}}
/>
);
}

Resources