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
Ok. I am super lost here. I am attempting to return an a value from a nested array of objects. Here is what the database looks like.
Each object returns an array of staff as seen in this console log.
I cannot for the life of me display both names out of the array. I used the .flatMap() function to extract the data from the array, but when I go to render it in the component only the first name shows. Here is my codebase. Right now I am just console logging the data using .flatMap()
import React, { Fragment, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Table } from 'react-bootstrap';
import Moment from 'react-moment';
import Button from '../components/Button';
import ActivitySummary from '../components/ActivitySummary';
import { projectsInfoDetails } from '../actions/projectInfoActions';
import { projectContacts } from '../actions/projectContactActions';
import { projectStaff } from '../actions/accountableStaffActions';
import SectionHeader from '../components/SectionHeader';
import Loader from '../components/Loader';
import Message from '../components/Message';
const ProjectScreen = ({ match }) => {
const dispatch = useDispatch();
const projectInfoDetails = useSelector(state => state.projectInfoDetails);
const { loading, error, projects } = projectInfoDetails;
const contactDetails = useSelector(state => state.projectContactDetails);
const { projectContact } = contactDetails;
const projectAccountableStaff = useSelector(state => state.projectStaff);
const { accountableProjectStaff } = projectAccountableStaff;
useEffect(() => {
dispatch(projectsInfoDetails(match.params.id));
dispatch(projectContacts(match.params.id));
dispatch(projectStaff(match.params.id));
}, [dispatch, match]);
const lastName = projectContact.map(l => l.contact.lastName);
const firstName = projectContact.map(f => f.contact.firstName);
const accountableStaffLastNames = accountableProjectStaff.flatMap(
({ accountableStaff }) => accountableStaff.map(data => data.lastName)
);
console.log(accountableStaffLastNames);
return (
<Fragment>
<div>
<SectionHeader sectionName='Project' />
<Button buttonName='Edit Project' />
</div>
{loading ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</Message>
) : (
<div style={{ backgroundColor: '#F8F8F8' }}>
<Table className='borderless'>
<tbody>
<tr>
<td>
<strong>Name: </strong>
{projects.name}
</td>
<td>
<strong>Status: </strong>
{projects.status}
</td>
</tr>
<tr>
<td>
<strong>State: </strong>
{projects.state}
</td>
<td>
<strong>County: </strong>
{projects.county}
</td>
</tr>
<tr>
<td>
<strong>Congressional District: </strong>
{projects.district}
</td>
<td>
<strong>Type: </strong>
{projects.type}
</td>
</tr>
<tr>
<td>
<strong>Funding Source: </strong>
<br />
{`${projects.fundingSource} ${projects.fundingSourceName}`}
</td>
<td>
<strong>Funding Source Goal: </strong>
<br />
{projects.fundingSourceGoal}
</td>
<td>
<strong>Start Date: </strong>
<br />
<Moment format='MM/DD/YYYY'>{projects.startDate}</Moment>
</td>
<td>
<strong>End Date: </strong>
<br />
{projects.endDate === null ? (
''
) : (
<Moment format='MM/DD/YYYY'>{projects.endDate}</Moment>
)}
</td>
<td>
<strong>Funding Percent: </strong>
<br />
{projects.fundingPercent}
</td>
</tr>
<tr>
<td>
<strong>Contact: </strong>
{firstName} {lastName}
</td>
</tr>
<tr>
<td>
<strong>Start Date: </strong>
<Moment format='MM/DD/YYYY'>
{projects.projectStartDate}
</Moment>
</td>
<td>
<strong>End Date: </strong>
{projects.projectEndDate === null ? (
''
) : (
<Moment format='MM/DD/YYYY'>
{projects.projectEndDate}
</Moment>
)}
</td>
</tr>
<tr>
<td colSpan='5'>
<strong>Goals and Objectives: </strong>
{projects.goalsAndObjectives}
</td>
</tr>
<tr>
<td colSpan='5'>
<strong>Success Description: </strong>
{projects.successDescription}
</td>
</tr>
<tr>
<td>
<strong>Accountable Staff: </strong>
</td>
</tr>
<tr>
<td>
<strong>Project ID: </strong>
{projects.projectId}
</td>
</tr>
</tbody>
</Table>
</div>
)}
<ActivitySummary />
</Fragment>
);
};
export default ProjectScreen;
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>
)}
i have a problem that i need to add the data from state and loop it using map. in my project im using redux and got the value from redux its self but in the state won't render again after map.
i already tried to using this.props.sendNameProduct in my array of map but when i added the new product the first product updated with the value of last product. i just want it to store the first product and then when im inputting the second product , the first product still there.
class OpenPositions extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
console.log(this.props, "ini porpoaspdopa")
console.log(this.props.sendNameProduct, "ini send name")
console.log(this.props.sendNameProduct.sendNameProduct," ini kirik");
let dapetItem = this.props.cobaSend == null ? [] : this.props.cobaSend
let cobaSend = [{qty: '123'}];
let getItem = localStorage.getItem('storage')
let newData =[];
let newDataBaru = [];
let newArr = [];
newArr.push(this.props.cobaSend);
newData = newDataBaru.concat(newArr)
console.log(newArr, "ini new array");
console.log(newData, "ini new Data")
return (
<div style={{height:'100%', overflow:'auto'}}>
<table className="borderline" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<div>
<div>
<table style={{height:"100%", width:"100%"}}>
<tbody>
<tr align="center" className="fieldtitle fieldbg">
<td align="left">Items</td>
<td>Qty</td>
<td>Sold</td>
<td>Bought</td>
<td>Avail</td>
<td>Date</td>
<td>Options</td>
</tr>
</tbody>
<tbody className="divOP2">
{this.props.cobaSend.map((item, index) =>{
console.log(item, "ini item bois");
console.log(index, "ini index")
return(
<tr align="center" className="contentbg">
<td align="left" nowrap className="bggradientleft" style={{backgroundImage: ' url(https://demo.sgberjangka.com/images/background_gradientleft.gif)', backgroundRepeat: 'repeat-y', backgroundRepeatX: 'repeat', boxSizing: "border-box", border: "1px solid black", backgroundSize:"100%"}}><font color="#FFFFFF"><strong>{item.product}</strong></font></td>
<td>{item.qty}</td>
<td>{item.sell}</td>
<td>{item.buy}</td>
<td>{item.avail}</td>
<td>{item.date}</td>
<td>
<input
className="checkbox"
type="checkbox"
checked={this.state.isChecked}
onChange={this.handleCheckBox}
/>
</td>
</tr>
)})}
</tbody>
</table>
</div>
</div>
</td>
</tr>
<table className="normal" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<button type="submit" className="normalButton wide">GTC Order (Liq)</button>
</td>
<td>
<button type="submit" className="normalButton wide">Buy/Sell (Liq)</button>
</td>
</tr>
</tbody>
</table>
</tbody>
</table>
</div>
)
}
};
function stateProps(state){
console.log(state.main.sendNameProduct, "ini send Name Product")
console.log(state.main.sendValueSell, "ini send sell Product")
console.log(state.main.sendValueBuy, "ini send buy Product")
console.log(state.main.sendQuantity, "ini send qty Product")
return {
sendNameProduct : state.main,
sendValueSell : state.main,
sendValueBuy : state.main,
sendQuantity : state.main
};
};
function dispatchProps(dispatch){
return {
}
}
export default connect(
stateProps,
dispatchProps
)(OpenPositions);
the result its when im updating with new data the first one changed and got same values with new data.
lets assume with this.props.cobaSend got the objects like {product: "HKK50_BBJ", qty: "12", sell: "28579", buy: "--", avail: "12", …}, in mapping got the value product, qty ,sell ,and etc. but when im inserting the new data the value in map not updateing with the new array.
Your newData.map loop on the newData array, but display this.props.sendNameProduct... values in your DOM.
Might just be an error on accessing those values, try call the item return by the map callback :
{
newData.map((item, index) =>{
console.log(item, "ini item bois");
console.log(index, "ini index")
return(
<tr align="center" className="contentbg">
<td align="left" nowrap className="bggradientleft"><font color="#FFFFFF"><strong>{item.item}</strong></font></td>
<td>{item.qty}</td>
<td>{item.sell}</td>
<td>{item.buy}</td>
<td>{item.date}</td>
<td>{item.avail}</td>
<td>
<input
className="checkbox"
type="checkbox"
checked={this.state.isChecked}
onChange={this.handleCheckBox}
/>
</td>
</tr>
)
});
}
class OpenPositions extends Component {
constructor(props) {
super(props);
this.state = {
newArr : []
};
}
render() {
console.log(this.props, "ini porpoaspdopa")
console.log(this.props.sendNameProduct, "ini send name")
console.log(this.props.sendNameProduct.sendNameProduct," ini kirik");
console.log(this.props.cobaSend," ini COBA SEND");
// let dapetItem = this.props.cobaSend == null ? [] : this.props.cobaSend
// let cobaSend = [{qty: '123'}];
// let getItem = localStorage.getItem('storage')
let newArr = this.state.newArr;
newArr.push(this.props.cobaSend);
console.log(newArr, "ini new array");
console.log(newData, "ini new Data")
//let newData = [];
//let newDataBaru = newData.concat(data);
//newData.push(data[0])
//console.log(newData, "ini new Data")
//console.log(newDataBaru,"ini data baru")
//newData = newDataBaru.concat(data)
// for(let i =0 ; i< 5; i++){
// }
//console.log(newData, "ini new Data")
return (
<div style={{height:'100%', overflow:'auto'}}>
<table className="borderline" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<div>
<div>
<table style={{height:"100%", width:"100%"}}>
<tbody>
<tr align="center" className="fieldtitle fieldbg">
<td align="left">Items</td>
<td>Qty</td>
<td>Sold</td>
<td>Bought</td>
<td>Avail</td>
<td>Date</td>
<td>Options</td>
</tr>
</tbody>
<tbody className="divOP2">
{newArr.map((item, index) =>{
console.log(item, "ini item bois");
console.log(index, "ini index")
return(
<tr align="center" className="contentbg">
<td align="left" nowrap className="bggradientleft" style={{backgroundImage: ' url(https://demo.sgberjangka.com/images/background_gradientleft.gif)', backgroundRepeat: 'repeat-y', backgroundRepeatX: 'repeat', boxSizing: "border-box", border: "1px solid black", backgroundSize:"100%"}}><font color="#FFFFFF"><strong>{item.product}</strong></font></td>
<td>{item.qty}</td>
<td>{item.sell}</td>
<td>{item.buy}</td>
<td>{item.avail}</td>
<td>{item.date}</td>
<td>
<input
className="checkbox"
type="checkbox"
checked={this.state.isChecked}
onChange={this.handleCheckBox}
/>
</td>
</tr>
)})}
</tbody>
</table>
</div>
</div>
</td>
</tr>
<table className="normal" cellspacing="0" cellpadding="0" border="0" style={{height:'100%'}}>
<tbody>
<tr>
<td>
<button type="submit" className="normalButton wide">GTC Order (Liq)</button>
</td>
<td>
<button type="submit" className="normalButton wide">Buy/Sell (Liq)</button>
</td>
</tr>
</tbody>
</table>
</tbody>
</table>
</div>
)
}
};
im using state to store it there and then when im inputting the data its worked.
I am tryng to display search results for each key press on my input:
getMovies(e){
axios.get(`http://www.omdbapi.com/?t=${e.target.value}`)
.then((response) => {
this.setState({ movies: response.data });
})
.catch((error) => {
console.log(error);
});
}
render() {
return (
<div className="container">
<SearchForm onkeydown={this.getMovies} />
<MovieList movies={this.state.movies}/>
</div>
);
}
}
In my search form I bind my function to the FormControl onChange:
export default class SearchForm extends React.Component{
render(){
return(
<Row>
<Col md={6} >
<h2>Custom search field</h2>
<div className="custom-search-input">
<Col md={12} className="input-group" >
<FormControl
type="text"
bsSize="lg"
value={this.props.val}
placeholder="Enter text"
onChange={this.props.onkeydown.bind(this)}
/>
<span className="input-group-btn">
<button className="btn btn-lg" type="button">
<i className="glyphicon glyphicon-search"></i>
</button>
</span>
</Col>
</div>
</Col>
</Row>)
}
}
My movielist component:
export default class MovieList extends React.Component{
render(){
var userNodes = this.props.movies.map(function(movie){
return (
<tr key={movie.id}>
<td>{movie.Year}</td>
<td >{movie.Title}</td>
<td >{movie.Released}</td>
</tr>
)
});
return (
<div>
<Table responsive>
<thead>
<tr>
<th>id</th>
<th>Year</th>
<th>Title</th>
<th>Released</th>
</tr>
</thead>
<tbody>
{userNodes}
</tbody>
</Table>
</div>
);
}
}
I can get the response on the network panel, but the state is not updating to display the MovieList component.
How can I update the state and display it in my MovieList ?
I've checked that API and seems it returns an object, not an array.
Update 1
You can convert your component in something like:
export default class MovieList extends React.Component{
render(){
const { movie } = this.props;
return (
<div>
<Table responsive>
<thead>
<tr>
<th>Id</th>
<th>Year</th>
<th>Title</th>
<th>Released</th>
</tr>
</thead>
<tbody>
<tr>
<td>{movie.imdbID}</td>
<td>{movie.Year}</td>
<td>{movie.Title}</td>
<td>{movie.Released}</td>
</tr>
</tbody>
</Table>
</div>
);
}
}
and use it like:
<MovieList movie={this.state.movies} />
Please notice I'm using movie instead of movies.
Update 2:
You can also (and I would suggest doing this) convert your MovieList into a dumb functional component:
const MovieList = ({ movie }) => (
<div>
<Table responsive>
<thead>
<tr>
<th>Id</th>
<th>Year</th>
<th>Title</th>
<th>Released</th>
</tr>
</thead>
<tbody>
<tr>
<td>{movie.imdbID}</td>
<td>{movie.Year}</td>
<td>{movie.Title}</td>
<td>{movie.Released}</td>
</tr>
</tbody>
</Table>
</div>
)
export default MovieList;