Reload table after deleting an item from it with React
You should put your data in state and then change the state. After changing the state the page automatically re-rendered and changed data of your state will be shown.
So in your delete function simply delete your chosen data and give your remaining data to your state.
Hope this helps, feel free to ask questions if I couldn't explain myself clearly.
How to refresh page after deleting item in React?
I would suggest moving your delete call up to a function in Home that takes an id, and passing that function as a prop to RowCreator.
The state inside the RowCreator is never used and changing it doesn't really help you. What you want is to tell Home that there's been a change and it needs to update its state.
How to update table after delete request in reactjs?
Your delete function need a little rework. When you do the async axios delete call, you'll need to remove the data from your local state too.
handeldelete = async userId => {
await axios.delete("http://localhost:3000/admin/users/" + userId, {
headers: {
'x-access-token': localStorage.getItem("token")
}
});
this.setState((prev) => ({
tableRows: prev.tableRows.filter(
(row) => row.id !== userId
)
}));
};
I reproduce your app with fake data right here : https://codesandbox.io/s/goofy-herschel-vwe2s?file=/src/App.js
React refresh the page after delete button
The []
in the useEffect
hook is a dependency array to trigger the effect to run. If you want to trigger the effect (without it going off mercilessly), you can create a new variable that triggers that effect to run.
import React, { useState, useEffect } from "react";
import axios from "axios";
import Table from "../Table/Table";
import "./Display.css";
const Display = () => {
const [state, setState] = useState({ students: [], count: "" });
const [requestData, setRequestData] = useState(new Date());
const [searchItem, setsearchItem] = useState({
item: ""
});
const Search = e => {
setsearchItem({ item: e.target.value });
};
useEffect(() => {
axios
.get("/students")
.then(response => {
setState({
students: response.data.students,
count: response.data.count
});
})
.catch(function(error) {
console.log(error);
});
}, [requestData]);
const nameFilter = state.students.filter(list => {
return list.name.toLowerCase().includes(searchItem.item.toLowerCase());
});
return (
<div>
<h3 align="center">Student tables</h3>
<p align="center">Total students: {state.count}</p>
<div className="input-body">
<div className="row">
<div className="input-field col s6">
<input placeholder="search student" onChange={Search} />
</div>
</div>
</div>
<table className="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Date of birth</th>
<th>Address</th>
<th>Zipcode</th>
<th>City</th>
<th>Phone</th>
<th>Email</th>
<th colSpan="2">Action</th>
</tr>
</thead>
{nameFilter.map((object, index) => {
return (
<tbody key={index}>
<Table obj={object} setRequestData={setRequestData} />
</tbody>
);
})}
</table>
</div>
);
};
export default Display;
Then you can trigger it from your Table
component:
import React, { useState } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
const Table = props => {
const removeData = () => {
axios
.delete("/students/" + props.obj.id)
.then(() => {
props.setRequestData(new Date());
})
.catch(err => console.log(err));
};
return (
<React.Fragment>
<tr>
<td>{props.obj.name}</td>
<td>{props.obj.birthday}</td>
<td>{props.obj.address}</td>
<td>{props.obj.zipcode}</td>
<td>{props.obj.city}</td>
<td>{props.obj.phone}</td>
<td>{props.obj.email}</td>
<td>
<Link
to={"/edit/" + props.obj.id}
className="waves-effect waves-light btn"
>
Edit
</Link>
</td>
<td>
<button onClick={removeData} className="waves-effect red btn ">
Remove
</button>
</td>
</tr>
</React.Fragment>
);
};
export default Table;
Why do I have to refresh page manually after delete?
What you see in render is what you have in your state.
TL;DR
You need to update your state.
So you have two ways.
Optimistic update, fire delete api to server + setState to delete data in your state. And after you receive response from delete api, act accordingly.
After fire delete api, re-fetch the whole data from server again and update state.
I would suggest option 1 because it feels quicker for user.
Some extra concept here is.
If you want to share state (data) with your "CircuitList" and "CircuitDetail" page. You should store circuits in some parent, like App (or Redux state) and then pass them down to each component.
Again, the optimistic update pattern. Fire API + setState immediately... revert back if things go wrong.
Let me know if you feel like any more help :)
Below is what you can do.
// assuming you have your data in App, state.circuits
class App extends React.Component {
state = {
circuits: [
{ id: 1, title: 'Circuit 1' },
{ id: 2, title: 'Circuit 2' },
{ id: 3, title: 'Circuit 3' },
],
}
afterDeleteCircuit = (circuitID) => {
// state, before delete anything
const currentCircuits = this.state.circuits;
// Remove deleted item from state.
this.setState({
circuits: currentCircuits.filter(circuit => circuit.id !== circuitID),
});
// Fire delete API
axios
.delete(`link-to-api`, this.state)
.then(response => {
if (response.status === 'error') {
// Oops, something went wrong. Let's get that deleted Id back.
this.setState({
circuits: currentCircuits,
});
// Show Error message here.
} else {
// Delete successfully, do nothing.
// Because we already remove the deleted id from state.
// Show success message here.
}
});
}
render() {
return (
<Router>
<Route exact path='/' render={(props) => <CircuitList {...props} circuits={this.state.circuits} /> } />
<Route path='/circuits/:id' render={(props) => <CircuitDetail {...props} onDelete={this.afterDeleteCircuit} /> } />
</Router>
);
}
}
class CircuitList extends React.Component {
render () {
const { circuits } = this.props;
return (
<div>
{circuits.map(circuit => (
<li>{circuit.title} <Link to={`/circuit/${circuit.id}`}>Edit</Link></li>
)}
</div>
);
}
}
class CircuitDetail extends React.Component {
handleDelete = (e) => {
const { match, history } = this.props;
const id = match.params.id;
this.props.onDelete(id);
history.push('/');
}
render () {
return (
<div>
...
// Delete button
<button onClick={this.handleDelete}>Delete</button>
</div>
);
}
}
Update a Table with React Hooks when a Row is Added, Deleted and Modified? [Issue: Gets Before Post and Delete]
Well, you don't what to unconditionally call setData
within an useEffect
hook with data
as a dependency as this will cause an infinite loop (render looping) to occur.
Since the getValues
utility already unpacks the response.data
value there is likely no need to do it again in your UI. Also, remove the data
dependency.
useEffect(() => {
Axios.getValues()
.then((result) => {
setData(result.results);
});
}, []);
For the deleteValues
utility, if console.log("Delete Values: ", response);
is showing the correct values than I think you need to return this value from deleteValues
.
const deleteValues = (id) => {
console.log(id);
const deleteValues = axios
.delete("https://pokeapi.co/api/v2/type/${id}`)
.then((response) => {
console.log("Delete Values: ", response);
return response; // <-- new data values
})
.catch(function (error) {
console.log(error);
});
return deleteValues;
};
Then in ValuesTable
you need to update your data
state with the new deleted values.
{data.map((values) => {
...
<Button
onClick={() => {
Axios.deleteValues(values.id)
.then(data => setData(data));
}}
/>
...
})};
Update
Ok, since the deleteValues
utility doesn't return the updated data
from the backend you will need to maintain your local state manually. I suggest doing this work in a callback handler. Upon successful deletion, update the local state.
const [data, setData] = React.useState();
useEffect(() => {
Axios.getValues().then((result) => {
setData(result.data);
});
}, []);
const deleteHandler = id => async () => {
try {
await Axios.deleteValues(id); // no error, assume success
setData(data => data.filter((item) => item.id !== id));
} catch(err) {
// whatever you want to do with error
}
};
return (
...
{data.map((values) => {
<TableRow/>
<TableCell>{values.values}</TableCell>
<TableCell>
<Button onClick={deleteHandler(values.id)}>
Delete
</Button>
})};
...
)
Note that I've written deleteHandler
to be a curried function so you don't need an anonymous callback function for the button's onClick
handler. It encloses the current id
in an "instance" of the callback.
Update 2
If you are making a lot of different changes to your data in the backend it may just be easier to use a "fetch" state trigger to just refetch ("get") your data after each backend update. Anytime you make a call to update data in your DB, upon success trigger the fetch/refetch via a useEffect
hook.
const [data, setData] = React.useState();
const [fetchData, setFetchData] = useState(true);
const triggerDataFetch = () => setFetchData(t => !t);
useEffect(() => {
Axios.getValues().then((result) => {
setData(result.data);
});
}, [fetchData]);
const deleteHandler = id => async () => {
try {
await Axios.deleteValues(id); // no error, assume success
triggerDataFetch(); // <-- trigger refetch
} catch(err) {
// whatever you want to do with error
}
};
Related Topics
Expand Div on Click With Smooth Animation
How to Strip/Replace Something from a Url
Connecting to Tcp Socket from Browser Using JavaScript
How to Close Bootstrap 3 Dropdown When We Click Outside on a Tablet
Javascript, Viewing [Object Htmlinputelement]
How to Combine Object Values from Separate Lines into One Line
Search Bar With Dropdown Results
In React Why Does Calling a Function from Another Function in Our Code Not Work and Display
React-Router Go Back a Page How to Configure History
Make Angular.Foreach Wait for Promise After Going to Next Object
Hide Elements If User Logged In
How to Convert from Google Sheet Date Number Value to JavaScript Date
Html2Canvas Generates Blurry Images
How to Get the Url Parameters Using Angularjs
How Insert JavaScript into Vue File
Laravel - How to Pass a PHP Variable to a JavaScript Function from a Blade File