I am working on a react project I am trying to display data in td, the data is coming from backend and that data is coming in console. But I am not able to display data in table.
For this project I am using functional Component
This is my Child.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
export default function Child() {
const [oldEmployData, newEmployData] = useState([])
async function getEmploysData() {
try {
const response = await axios.get('http://localhost:1000/api/employList');
newEmployData(response.data);
console.log(response.data)
} catch(error) {
console.log(error)
}
}
useEffect(() => {
getEmploysData()
}, [])
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
<table className="table table-bordered">
<thead>
<tr>
<th>Employ Name</th>
<th>Employ Age</th>
<th>Employ Stream</th>
<th>Employ Address</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
<button className='btn btn-primary'>Edit</button>
</td>
<td>
<button className='btn btn-danger'>Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
)
}
If I am clear please put a comment
Assuming your axios request is responding with a valid JSON array, you can render that data directly into your table via Array#map() by extending your render logic as shown below:
<tbody>
{data.map(item =>
<tr key={item.id}>
{/* assuming each item in JSON array has firstName, lastName, email
and password fields */}
<td>{item.firstName}</td>
<td>{item.lastName}</td>
<td>{item.email}</td>
<td>{item.password}</td>
{/* suppose you have editItem() and deleteItem() defined, these
can be invoked (during click event) for each item like this */}
<td>
<button className="btn btn-primary"
onClick={() => editItem(item)}>Edit</button>
</td>
<td>
<button className="btn btn-danger"
onClick={() => deleteItem(item)}>Delete</button>
</td>
</tr>)}
</tbody>
An important point to note is that each <tr> element being mapped must have a key prop supplied with a value that is unique to the item being rendered/mapped. With that in mind, the assumption being made above is that each item in the data array has a unique id.
Suppose json data like this
let data = [
{id:1,name:'One'},
{id:2,name:'Two'},
{id:3,name:'Three'}
]
Iterate like this
{data.map(d=>
<tr key={d.id}>
<td>{d.name}</td>
<td>{}</td>
<td>{}</td>
<td></td>
<td><button className='btn btn-primary' onClick={()=>handleEdit(d.id)>Edit</button></td>
<td><button className='btn btn-danger' onClick={()=>handleDelete(d.id)}>Delete</button></td>
</tr>
)}
Related
Hi there I'm fairly new to react and I'm trying to create a student management app with React as a frontend and i can't seem to get the page to return a list of students since I tried working with the functions useHistory and useNavigate from react-router-dom to try redirect to an individual student component but I was unable to get them working on my project so I removed them.
The page was rendering the student objects from the backend API i created just fine before I tried implementing the two functions but now won't render any student object, all that is displayed are the table heads but not the table rows any help on what the problem would be appreciated
here is my hook component to fetch data before using useHistory & useNavigate
function GetAllStudents() {
const [students, setStudents] = useState([]);
const fetchData = async () => {
StudentService.getStudents() //axios service function used to fetch data
.then((res) => res.json())
.then((res) => {
const currentStudent = res.data;
setStudents(currentStudent); // try setStudents(res.data) if fails
})
.catch((err) => {
console.log(err);
});
// fetchData();
};
useEffect(() => fetchData(), []);
return (
<div class="container">
<div class="form container p-4">
<h1>Week 10 - React Frontend </h1>
<a href="/add" class="btn btn-success">
Add Student
</a>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{students.map((student) => (
<tr key={student.id}>
<td> {student.firstname} </td>
<td> {student.lastname}</td>
<td> {student.email}</td>
<td>
<button className="btn btn-info">Edit</button>
<button
style={{ marginLeft: '10px' }}
className="btn btn-danger"
onclick="return confirm('Do you Really want to delete')">
Delete{' '}
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
export default GetAllStudents;
When I inspect elements on my browser it shows the state is not saving the objects to the array
I don't know what I misconfigured because even when I change the function to a class component that also previously worked properly doesn't display the objects anymore
import React, { Component } from 'react';
import StudentService from '../services/StudentService';
class GetAllStudents extends Component {
constructor(props) {
super(props);
this.state = {
students: [],
};
this.addStudent = this.addStudent.bind(this);
this.editStudent = this.editStudent.bind(this);
this.deleteStudent = this.deleteStudent.bind(this);
}
deleteStudent(id) {
StudentService.deleteStudent(id).then((res) => {
this.setState({
students: this.state.students.filter((student) => student.id !== id),
});
});
}
updateStudent(id) {
this.props.history.push(`/students/${id}`); // props(parameter) to navigate to edit student component
}
editStudent(id) {
this.props.history.push(`/edit/${id}`); // props(parameter) to navigate to edit student component
}
componentDidMount() {
StudentService.getStudents().then((res) => {
this.setState({ students: res.data }); //loads all students in database
});
}
addStudent() {
this.props.history.push('/add'); //function to navigate to edit student component with form to add student
}
render() {
return (
<div class="container">
<div class="form container p-4">
<h1>Week 10 - React Frontend </h1>
<a href="/add" class="btn btn-success">
Add Student
</a>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{this.state.students.map((student) => (
<tr key={student.id}>
<td> {student.firstname} </td>
<td> {student.lastname}</td>
<td> {student.email}</td>
<td>
<button
onClick={() => this.updateStudent(student.id)}
className="btn btn-info">
Edit
</button>
<button
style={{ marginLeft: '10px' }}
onClick={() => this.deleteStudent(student.id)}
className="btn btn-danger"
onclick="return confirm('Do you Really want to delete')">
Delete{' '}
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}
export default GetAllStudents;
when I check my backend it shows calls are being made to the server but react isn't fetching or displaying data
any help on how to solve this problem would be appreciated as I currently don't know what I did wrong
I am implementing a table in react and I want to search data in tables based on two factors, i.e., Filter-By-Name and Filter-By-Consultant. You can see the expected output here
Now the problem is that I have implemented Search-By-Name successfully and it works fine. Now I coded the Search-By-consultant but I don't know how to call it in the table body along with Search-By-Name.
Here is my Bookings.js. I Know I have to call FilteredConsultants in the table body along with FilteredNames but how to do that?
import React, {useState, useEffect} from 'react';
import axios from 'axios';
import {Link} from 'react-router-dom';
import '../../static/Bookings.css';
import {BsFilterRight} from "react-icons/bs";
const Bookings= ()=>{
const[Bookings, setBooking]=useState([]);
const[searchByName, setSearchByName]=useState('');
const[FilteredNames, setFilteredNames]=useState([]);
const[searchByConsultant, setSearchByConsultant]=useState('');
const[FilteredConsultants, setFilteredConsultants]=useState([]);
useEffect(()=>{
loadUsers();
}, []);
useEffect(()=>{
setFilteredNames(
Bookings.filter(Booking=>{
return Booking.name.toLowerCase().includes(searchByName.toLowerCase())
})
)
}, [searchByName, Bookings]);
useEffect(()=>{
setFilteredConsultants(
Bookings.filter(Booking=>{
return Booking.consultant.toLowerCase().includes(searchByConsultant.toLowerCase())
})
)
}, [searchByConsultant, Bookings]);
const loadUsers= async()=>{
const result =await axios.get("http://localhost:3001/Bookings");
setBooking(result.data.reverse());
};
const deleteUser=async id => {
await axios.delete(`http://localhost:3001/Bookings/${id}`);
loadUsers();
}
return(
<div className="Booking-page-container">
<h2 className="text-center mb-4">Bookings Page</h2>
<table class="table table-bordered table-striped border shadow">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">
<BsFilterRight/>
<input
placeholder="search by name..."
onChange={e=>setSearchByName(e.target.value)}
/>
</th>
<th scope="col">
<BsFilterRight/>
<input
placeholder="search by consultant..."
onChange={e=>setSearchByConsultant(e.target.value)}
/>
</th>
<th scope="col">Email</th>
<th>Action</th>
</tr>
</thead>
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th scope="col">Name</th>
<th scope="col">Consultant</th>
<th scope="col">Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{FilteredNames.map((Booking,index)=>(
<tr>
<th scope="row">{index+1}</th>
<td>{Booking.name}</td>
<td>{Booking.consultant}</td>
<td>{Booking.email}</td>
<td>
<Link class="btn btn-primary mr-2" to={`/Bookings/view/${Booking.id}`}>View</Link>
<Link class="btn btn-outline-primary mr-2" to={`/Bookings/edit/${Booking.id}`}>Edit</Link>
<Link class="btn btn-danger" onClick={()=>deleteUser(Booking.id)}>Delete</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Bookings;
Right now, once searchByConsultant or searchByName is changed Table is displaying Bookings filtered by only one of the values.
It you would like to filter with 'and' condition, then you would need to construct filter using both of values.
useEffect(()=>{
setFilteredNames(
Bookings.filter(Booking=> {
const byName = !searchByName || Booking.name.toLowerCase().includes(searchByName.toLowerCase());
const byConsultant = !searchByConsultant || Booking.consultant.toLowerCase().includes(searchByConsultant.toLowerCase());
return byName && byConsultant;
})
)
}, [searchByName, searchByConsultant, Bookings]);
+ FilteredConsultants seems that isn't really used here
I have a dynamic table whose items I render through a list. The idea is that, on clicking the name of a row, a modal will open and that will print certain values retrieved from the backend server.
When I click on a specific person's name, the modal loads for all elements in the table. How do I fix this?
The rendered code for the table is as follows:-
<table className="table">
<thead>
<tr>
<th>S. NO.</th>
<th>NAME</th>
<th>ADDRESS</th>
<th>TELEPHONE</th>
<th>EMAIL</th>
<th>AGE</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.personData.map((pRow, idx) => (
<>
<PopUp hideModal={this.hideModal} show={this.state.show} id={siteRow.id} />
<tr key={pRow.id}>
<td>{idx + 1}</td>
<td> <a onClick={this.showModal}> {pRow.name} </a> </td>
<td>{pRow.address}</td>
<td>{pRow.phone}</td>
<td>{pRow.email}</td>
<td>{pRow.age}</td>
<td>
{" "}
<DeleteButton id={pRow.id} onDelete={this.onDelete} />{" "}
</td>
</tr>
</>
</tbody>
</table>
In the code for the table, the placement of the PopUp component is such because I want to pass the ID of the particular site to the modal.
This is the rendered code for the modal:-
showModal(e) {
this.setState({
show: true
});
}
hideModal(e) {
this.setState({
show:false
});
this.props.hideModal && this.props.hideModal(e);
}
render() {
if(!this.props.show){
return null;
}
return (
<>
<div>
The ID of the person is: {this.props.id}
<button type="button" className="btn theButton" onClick={this.hideModal}>CLOSE</button>
</div>
</>
);
}
This is very rudimentary code and I haven't added much CSS so this just opens up in the table itself. I want to change this but given the placement of the PopUp component and the fact that I want to pass the ID to the component, I'm not sure how to go about it.
The problem is that you have a series of Popups, but only a variable controlling their visibility. Consider replacing the show state as a simple visibility with a showId one, meant as the "id" of the Popup to be shown.
showModal(id) {
this.setState({
showId: id
});
}
hideModal(e) {
this.setState({
showId: null
});
this.props.hideModal && this.props.hideModal(e);
}
Then:
<table className="table">
<thead>
<tr>
<th>S. NO.</th>
<th>NAME</th>
<th>ADDRESS</th>
<th>TELEPHONE</th>
<th>EMAIL</th>
<th>AGE</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.personData.map((pRow, idx) => (
<>
<PopUp hideModal={this.hideModal} show={this.state.showId === pRow.id} id={siteRow.id} />
<tr key={pRow.id}>
<td>{idx + 1}</td>
<td> <a onClick={() => this.showModal(pRow.id)}> {pRow.name} </a> </td>
<td>{pRow.address}</td>
<td>{pRow.phone}</td>
<td>{pRow.email}</td>
<td>{pRow.age}</td>
<td>
{" "}
<DeleteButton id={pRow.id} onDelete={this.onDelete} />{" "}
</td>
</tr>
</>
</tbody>
</table>
I did not try the code, but I think it should work.
I'm getting "Objects are not valid as a React child" on this block:
<table className="table">
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Genre</th>
<th scope="col">Stock</th>
<th scope="col">Rate</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{movies.filter(movie => (
<tr key={movie._id}>
<td>{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
<Like
onClick={() => this.handleLike(movie)}
liked={movie.liked}
/>
</td>
<td>
<button
onClick={() => this.handleDelete(movie._id)}
className="btn btn-danger m-2"
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
The exact error message reads: Error: Objects are not valid as a React child (found: object with keys {_id, title, genre, numberInStock, dailyRentalRate, publishDate, liked}). If you meant to render a collection of children, use an array instead.
No matter what I do to troubleshoot this the error won't go away. Can anyone explain ?
This:
<tbody>
{movies.map(movie => (
<tr key={movie._id}>
<td>{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
<Like
onClick={() => this.handleLike(movie)}
liked={movie.liked}
/>
</td>
<td>
<button
onClick={() => this.handleDelete(movie._id)}
className="btn btn-danger m-2"
>
Delete
</button>
</td>
</tr>
))}
</tbody>
Should look like this:
<tbody>
<MovieComponent
movie={movie}
likeOnCLick={this.handleLike(movie)}
/>
</tbody>
You're not filtering anything, so just use map(), and pass the results into a React.Component that you define elsewhere.
The filter method is used to select certain items of an array. It seems that you have confused this with the map method, which should work in this scenario.
filter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Say I have a table that stores items and their weights and I want to sum the total weight from that column and display that at the top on the table. Not using anything other than react/jsx. For more clarification, my table is pulling data stored on a node.js/express server.
I tried writing a function to go into my table component that used reduce, it did not work at all and I'm not sure how to go about it at this point.
Would like the total weight to be displayed next to the table header.
const GearTable = (props) => {
return(
<div style={styles.box}>
<h3>Your Gear Locker</h3>
<br />
<br />
<Table hover style={[styles.font, styles.box]}>
<thead>
<tr>
<th>ID</th>
<th>Item Name</th>
<th>Description</th>
<th>Weight</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
{props.gear.map((gear, id) => {
return(
<tr key={id}>
<th scope="row" style={styles.font}> {gear.id}</th>
<td style={styles.font}> {gear.itemName}</td>
<td style={styles.font}> {gear.description}</td>
<td style={styles.font}> {gear.weight.value}</td>
<td style={styles.font}> {gear.quantity}</td>
<td>
<Button className="btn btn-secondary" size="lg" style={styles.font} id={gear.id} onClick={e => props.update(e, gear)}>Update Locker</Button>
<Button className="btn btn-secondary" size="lg" style={styles.font} id={gear.id} onClick={props.delete}>Delete Item</Button>
</td>
</tr>
)
})
}
</tbody>
</Table>
</div>
);
}
const GearTable = (props) => {
return(
Your Gear Locker
ID
Item Name
Description
Weight
Quantity
{props.gear.map((gear, id) => {
return(
{gear.id}
{gear.itemName}
{gear.description}
{gear.weight.value}
{gear.quantity}
props.update(e, gear)}>Update Locker
Delete Item
)
})
}
);
}