How to get value from Promise & use that later? - reactjs

Let me explain the issue, I am trying to show some details in a modal. I am using table in the modal to show details. In one section, I need the product name which is returned from a database query and I have to use that value returned from the database. The code for table is as follows:
<tbody>
{item.cartItems.map((item, i) =>
<tr key={item._id}>
<th scope="row">{i + 1}</th>
<th><img src={`${API}/product/photo/${item.product}`} alt={item.product.name} width="60px" height="50px" /></th>
<td>{**data returned from database**}</td>
<td align="center">{item.count}</td>
<td align="center">৳ {item.price * item.count} </td>
</tr>
)}
</tbody>
To get the data from the database, I am using a function
const getProdcutName = id => {
var productName;
getProductDetails(id)
.then(response => {
productName = response.data.name;
});
return productName;
}
But I can't access the value. The main thing is, in every Iteration I need to send the {item.product} to getProductName(id) and I need the name from the database in return. But I can't access the data from promise scope to return it.

This is the solution to my issue. Thanks to everyone who helped me out.
const CartItem = ({ item, i }) => {
const [productName, setProductName] = useState();
useEffect(() => {
getProductDetails(item.product)
.then(res => { setProductName(res.data.name) });
}, []);
return (
<tr key={item._id}>
<th scope="row">{i + 1}</th>
<th><img src={`${API}/product/photo/${item.product}`} alt={item.product.name} width="60px" height="50px" /></th>
<td>{productName == undefined ? "Getting Name" : productName}</td>
<td align="center">{item.count}</td>
<td align="center">৳ {item.price * item.count} </td>
</tr>
)}
And to send items to the cartItem
<tbody>
{item.cartItems.map((item, i) =>
<CartItem item={item} i={i} key={item._id} />
)}
</tbody>

Related

How to spilt a column into different rows table ReactJS

i would like to output 10 times before changing column, I saw some other examples but I didn't understand, im quite new to react. Furthermore i would like to show different timeslots in the first column 07:00-08:30, 08:30-10 and so on, with the setup i have at the moment how would i go about doing that?
function BookingTable() {
useEffect(() => {
Axios.post('http://localhost:3001/api/get/week1').then((response) => {
setIsBooked(response.data)
console.log(response.data);
})
}, []);
const [isBooked, setIsBooked] = useState([])
const renderTableData = () => {
return isBooked?.map((val) => (
<tr class>
<td></td>
<td>{val.booked}</td>
</tr>))
}
return (
<table id="table">
<thead>
<tr>
<th> </th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Satuday</th>
<th>Sunday</th>
</tr>
</thead>
<tbody>
{renderTableData()}
</tbody>
</table>
)
}
export default BookingTable

Assistance with using .map

How can I use .map so I can get the data for rentals and display the movie title as well? Do I use two .map functions or do I have to use a useEffect?
Movies
Id
Name
Price
Rentals
Id
Movie Id
Date Rented
Customer email
const RentalPage = () => {
const [movies, setMovies] = useState([]);
const [rentals, setRentals] = useState([]);
useEffect(() => {
fetchRentals(setRentals);
}, []);
useEffect(() => {
fetchMovies(setMovies);
}, []);
return (
<div>
<div>
<div>
<table>
<thead>
<tr>
<th>Customer Email</th>
<th>Movie Title</th>
<th>Purchase Date</th>
<th>Price</th>
</tr>
</thead>
{rentals.map((rental) => (
<tbody key={rental.id}>
<tr>
<td>{rental.customerEmail}</td>
<td >{movie.movieTitle}</td> <----------- (How do I use .map to get movie name)
<td>{rental.purchaseDate}</td>
<td>{rental.price}</td>
</tr>
</tbody>
))}
</table>
</div>
</div>
</div>
);
}
My question is since I am already using .map, can I use it again with different data without changing the database?
You can use find or filter
{rentals.map((rental) => {
// find
const movie_title = movies.find(movie => movie.id === rental.movieId).movieTitle
// or by filter
let _movie_title = movies.filter(movie => movie.id === rental.movieId)[0].movieTitle
return <tbody key={rental.id}>
<tr>
<td>{rental.customerEmail}</td>
<td >{movieTitle}</td>
<td>{rental.purchaseDate}</td>
<td>{rental.price}</td>
</tr>
</tbody>
})}
find returns the element that matches in the criteria, and filter returns a sublist of items that matched the criteria.

I'm trying to display search results for both name and genres for particular TV shows in React, how to use one filter method for both name and genre?

My table.js file below. I've managed to search and filter through my table in order to display search results for show by name, but not sure how to implement a second condition so that the same search bar can be used to display searches for shows by genre.
Genres is an array, like so: genres: ["Drama", "Action", "Adventure"]
As I said previously, I'm able to filter through shows using the user input to find shows by name, but I'd like to use that same filter function to also display results by genre. Any help would be hugely appreciated.
export default class Table extends Component {
constructor(props) {
super(props);
this.state = {
searchByTitle: ""
};
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
this.setState({searchByTitle : event.target.value})
}
renderRow(show) {
return (
<tr key={show.id}>
<td className="border border-green-600">
{show.image && (
<img className="w-full" src={show.image.medium} alt={show.name} />
)}
</td>
<td className="border border-green-600 bg-green-100">{show.name}</td>
<td className="border border-green-600 bg-green-100">
{show.genres.join(", ")}
</td>
<td className="border border-green-600 bg-green-100">{show.runtime}</td>
<td className="border border-green-600 bg-green-100">
{show.network && show.network.name}
</td>
<td className="border border-green-600 bg-green-100">{show.status}</td>
</tr>
);
}
render() {
const filterShows = (shows, query) => {
if (!query) {
return shows;
}
return shows.filter((show) => {
const showName = show.name.toLowerCase();
// const showGenres = show.genres.join(", ")
return showName.includes(query)
})
}
const filteredShows = filterShows(this.props.shows, this.state.searchByTitle)
return (
<table className="table-fixed border-collapse">
<thead>
<tr>
<input
type="text"
id="header-search"
placeholder="Search shows"
name="search"
onChange={this.handleChange}
/>
</tr>
<tr>
<th className="w-1/12">Poster</th>
<th className="w-4/12">Name</th>
<th className="w-4/12">Genres</th>
<th className="w-1/12">Runtime</th>
<th className="w-1/12">Network</th>
<th className="w-1/12">Status</th>
</tr>
</thead>
<tbody>{filteredShows.map((show) => this.renderRow(show))}</tbody>
</table>
);
}
}
Nevermind, I got it! Thank you to anyone who tried to help.
Just had change up my filterShows function so that it joined the array and then used toLowerCase(). See below:
const filterShows = (shows, query) => {
if (!query) {
return shows;
}
return shows.filter((show) => {
const showName = show.name.toLowerCase();
const showGenres = show.genres.join(", ").toLowerCase();
// const showGenre = show.genres;
return showName.includes(query) || showGenres.includes(query);
});
};

Update React table after deleting row

I'm new to React and have created a dynamic tablefrom a JSON received from the back-end server that I have. For each table row I have a button that opens to a dropdown which has two options - to edit the information in the row and to delete the row. I've made a separate component for the dropdown button and presently am passing the ID of the row to it.
With the present code, I'm able to delete the row but can only see the change on refreshing the page. I've looked at other answers to problems like mine with people saying the state needs to be updated but I'm confused about how to go about it in this case.
EDIT: I'm not use anything for managing state. Just plain simple React
This is the code for the table that gets rendered :-
<table className="table">
<thead>
<tr>
<th>S. NO.</th>
<th>NAME</th>
<th>AGE</th>
<th>ADDRESS</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.personData.map((Row, idx) => (
<tr key={Row.id}>
<td>{idx + 1}</td>
<td>{Row.name}</td>
<td>{Row.age}</td>
<td>{Row.addr}</td>
<td>
{" "}
<DropDownButton id={Row.id} />{" "}
</td>
</tr>
))}
</tbody>
</table>
This is the code in the DropDownButton component :-
handleDelete() {
console.log("ID " + this.props.id);
fetch("http://localhost/person/" + this.props.id, {
method: "DELETE",
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type"
}
})
.catch(error => console.log("Error:", error))
.then(response => console.log("Success:", response));
}
render() {
return (
<React.Fragment>
<div className="dropdown">
<button
type="button"
className="btn dropdown-toggle dropdownButton"
data-toggle="dropdown"
>
OPTIONS
</button>
<div className="dropdown-menu">
<p className="dropdown-item" onClick={this.handleEdit}>
EDIT
</p>
<p className="dropdown-item" onClick={this.handleDelete}>
DELETE
</p>
</div>
</div>
</React.Fragment>
);
}
}
In your parent component you need to make a callback method that will remove the data from this.state.personData like the method I wrote below
onDelete = (id) => {
this.setState({
...this.state,
personData: this.state.personData.filter((row) => row.id !== id)
});
}
render = () => {
return (
<table className="table">
<thead>
<tr>
<th>S. NO.</th>
<th>NAME</th>
<th>AGE</th>
<th>ADDRESS</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.personData.map((Row, idx) => (
<tr key={Row.id}>
<td>{idx + 1}</td>
<td>{Row.name}</td>
<td>{Row.age}</td>
<td>{Row.addr}</td>
<td>
{" "}
<DropDownButton id={Row.id} onDelete={this.onDelete} />{" "}
</td>
</tr>
))}
</tbody>
</table>
);
};
And then in your DropDownButton you need to call this onDelete callback
handleDelete () {
console.log("ID " + this.props.id);
fetch("http://localhost/person/" + this.props.id, {
method: "DELETE",
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type"
}
})
.catch(error => console.log("Error:", error))
.then(response => {
// call the passed in onDelete method here with the cooresponding id
this.props.onDelete(this.props.id);
console.log("Success:", response)
});
}
render () {
// ...
}
when this onDelete callback is called, the state in the parent component will change, causing it to rerender the list with only the items in the new list
I have a problem that may be related to what is discussed in this thread.
After adding or editing a column I am changing the color of the cells, but when I delete a row even though the state has changed the the cell colors remain intact until I change the pagination.
Edited
Following stackOverflow's behavioral steps, create a separate thread to address the problem.
In case someone has the same problem you can see the solution to the problem in this thread.

I can't find where the issue is in my code,my delete function is deleting everything in the state but is not deleting a customer in the database

I can't find where the issue is in my code,my delete function is deleting everything in the state but is not deleting a customer in the database.Can someone tell me where the issue is? I checked on my HTTP route and it seems fine. I also tried removing all the conditions to see if it works but it deletes all the records in the view but not in the database.Am I missing something?Thanks.
This is my delete function code:
deleteCustomer(id){
let confirmDeletion = window.confirm('Do you really wish to delete it?');
if (confirmDeletion) {
fetch('api/Customer/Delete/' + id, {
method:'delete'
})
.then(data => {
this.setState(
{
cusList: this.state.cusList.filter((rec) => {
return (rec.customerId != id);
})
});
});
}
}
This is my render where all the data is deleted when a delete button of one customer is clicked
and then displays"No customers yet":
renderCustomerTable = (cusList) => {
return (
<table className="ui celled fixed single line table">
<thead className="">
<tr className="">
<th className="">Name</th>
<th className="">Address</th>
<th className="">Action</th>
<th className="">Action</th>
</tr>
</thead>
<tbody className="">
{!cusList || cusList.length <=0 ?
<tr><td colSpan="6" align="center"><b>No Customers yet</b></td></tr>
:this.state.cusList.map(cus =>
<tr className="" key={cus.customerId}>
<td className="">{cus.name}</td>
<td className="">{cus.address}</td>
<td className="">
<Button className="ui yellow icon left labeled button " ><i aria-
hidden="true" class="edit icon"></i>Edit</Button>
</td>
<td className="">
<Button className="ui red icon left labeled button " onClick={(id) =>
this.deleteCustomer(cus.customerId)}><i aria-hidden="true" class="delete icon">
</i>Delete</Button>
</td>
</tr>
)}
</tbody>
</table>);
}
This is my controller:
[HttpGet]
[Route("api/Customer/Details/{id}")]
public Customer Details(int id)
{
return objcustomer.GetCustomerData(id);
}
This is my customerdataaccess:
public int DeleteCustomer(int id)
{
try
{
Customer cus = db.Customer.Find(id);
db.Customer.Remove(cus);
db.SaveChanges();
return 1;
}
catch
{
throw;
}
}
```
Try this.
fetch(`/api/Customer/Delete/${id}`, {
method:'delete'
})
.then(data => {
this.setState(prevState=>({
cusList: prevState.cusList.filter((rec)=>rec.customerId != id)
});
});

Resources