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.
Related
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>
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
I am trying to create a table looking for data from firebase, however the table is always giving error.
I put the whole function in a script to validate if any error in the component call, but always lists the same error: TypeError: custos.map is not a function
Does anyone know what can it be?
I already tested it and the variable custos can return the object, but I can't use it in the map function
function MeusCustos(){
const [custos, setCustos] = useState([]);
const [pesquisa, setPesquisa] = useState('');
const usuarioEmail = useSelector(state => state.usuarioEmail);
let listaCustos = [];
useEffect( () => {
firebase.firestore().collection('custos').get().then(async(resultado) => {
resultado.docs.forEach(doc => {
listaCustos.push({
id: doc.id,
...doc.data()
});
});
setCustos(JSON.stringify(listaCustos));
});
}, []);
return(
<>
<Navbar/>
<div className="row p-3">
<div className="container">
<h1>Simple Inventory Table</h1>
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Titulo</th>
<th scope="col">Descrição</th>
<th scope="col">Quantidade</th>
<th scope="col">Valor</th>
<th scope="col">Data</th>
<th scope="col">Comprovante</th>
<th scope="col">UsuarioEmail</th>
<th scope="col">Visualizações</th>
<th scope="col">Publico</th>
<th scope="col">Criação</th>
</tr>
</thead>
<tbody>
{custos.map( item =>
<tr >
<th scope ="row"></th>
<td>{item.titulo}</td>
<td>{item.descricao}</td>
<td>{item.quantidade}</td>
<td>{item.valor}</td>
<td>{item.data}</td>
<td>{item.comprovante}</td>
<td>{item.usuarioemail}</td>
<td>{item.visualizacoes}</td>
<td>{item.publico}</td>
<td>{item.criacao}</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
</>)
}
export default MeusCustos;
The problem is in your useEffect hook. Do not stringfy the array because it will become a string and the map function works on arrays, change setCustos(JSON.stringify(listaCustos)); so that your useEffect will look as follows:
useEffect( () => {
firebase.firestore().collection('custos').get().then(async(resultado) => {
resultado.docs.forEach(doc => {
listaCustos.push({
id: doc.id,
...doc.data()
});
});
setCustos(listaCustos);
});
}, []);
I found the problem, one of the values had been written with sysdate, which brought data of seconds and nanoseconds breaking the date component
Tks 4 help guys
I have an array which contains multiple objects like this:
const locations = [
{
information: ["Data Analyst", "Uruguay", "Montevideo", "$30,000"],
},
{
information: ["CTO", "UK", "Manchester", "$75,000"],
}
];
And I want to display each array in a new table row containing a <td> with each string.
Currently I have done this:
<tr>
{locations.map((location) => <td>{location.information}</td>)};
</tr>
Which returns each piece of information on a <td>
This is how the data looks at the minute:
And how it's meant to look
For this you have to use Array.map() like:
// To create tha table body by iterating data array
{
locations.map((location, locationIndex) =>
<tr key={locationIndex}>
<td>{location.information[0]}</td>
<td>{location.information[1]}</td>
<td>{location.information[2]}</td>
<td>{location.information[3]}</td>
</tr>
)
}
// In case you don't want to harcode the array index
{
locations.map((location, locationIndex) =>
<tr key={locationIndex}>
location.information.map((loc, locIndex) =>
<td key={locIndex}>{loc}</td>
)
</tr>
)
}
Change the code from,
<tr>
{locations.map((location) => <td>{location.information}</td>)};
</tr>
To:
<table border="1" width="100%" className="component_useRefBox">
<tbody>
{locations.map((location, i) => {
return (
<tr key={i}>
{location.information.map((data, j) => {
return <td key={j}> {data} </td>;
})}
</tr>
);
})}
</tbody>
</table>
To display two records row by row, you need to move {locations.map((location) .... )} above <tr> ... </tr> tag, because while using map method only each row will get iterated and you will get two separate rows..
{locations.map((location, i) => {
return (
<tr>
....
</tr>
)})}
As location.information is of array data, you cannot assign it directly.
You need to iterate using map and display each data like,
{location.information.map((data) => {
return <td> {data} </td>;
})}
When I log the values from snap parameter it is displaying the values there but the rows created by renderTable function aren't rendered in a browser.
function Employees() {
const rootRef = firebase
.database()
.ref()
.child("Employees");
const renderTable = () => {
var i = 0;
return rootRef.on("value", snap => {
snap.forEach(keys => {
i++;
return (
<tr key={keys}>
...
</tr>
);
});
});
};
return (
<div className={styles.Employee}>
<h1 className={styles.header}>Employees</h1>
<table>
<thead>
<tr>
...
</tr>
</thead>
<tbody>{renderTable()}</tbody>
</table>
</div>
);
}
export default Employees;
Seems like firebase's on() method invokes callback asynchronously. You must change your approach and use state and lifecycle in your React component, ie. with some help of hooks useEffect and useState as well as map method instead of forEach. In example:
function Employees() {
const [employees, setEmployees] = useState([]);
useEffect(() => {
firebase
.database()
.ref()
.child("Employees")
.on("value", setEmployees);
}, []);
const renderTable = () => {
return employees.map((employee, i) => {
return (
<tr key={keys}>
...
</tr>
);
});
};
return (
<div className={styles.Employee}>
<h1 className={styles.header}>Employees</h1>
<table>
<thead>
<tr>
...
</tr>
</thead>
<tbody>{renderTable()}</tbody>
</table>
</div>
);
}
export default Employees;
This the where rootRef is refering to
So I updated this and it kinda works.When I log The Emp attribute in JSX it contains an array of Table rows which is how it is suppose to be. When I do this it is Rendering the last node of array. and when i use .map function on it to render all of the array it shows this error TypeError: Emps.map is not a function.
How else am i suppose to render this array?
function Employees() {
const rootRef = firebase.database().ref().child("Employees")
var i = 0
const [Emps, setEmployees] = useState([])
useEffect(() => {
rootRef.on('value', snap => {
snap.forEach(keys => {
i++
setEmployees(
<tr>
<td>{i}</td>
<td>{keys.child("Name").val()}</td>
<td>{keys.child("employee_type").val()}</td>
<td>{keys.child("email").val()}</td>
<td>{keys.child("phoneNum").val()}</td>
<td>
<input className={styles.view} name="view" type="submit" value="View"/>
</td>
</tr>
)
})
})
}, [])
return (
<div className={styles.Employee}>
<h1 className={styles.header}>Employees</h1>
<table>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Employee Type</th>
<th scope="col">Email</th>
<th scope="col">Phone #</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{
Emps
}
</tbody>
</table>
</div>
)
}
export default Employees