I'm trying to create a table filled by a REST API using ReactJS. The problem is I don't know what I'm doing wrong with the sintax... I'm using ES6.
This is the FooTable:
import React from 'react'
import Foo from './Foo'
export default class FooTable extends React.Component {
render() {
return(
<tr>
<td>id</td>
<td>name</td>
<td>surname</td>
</tr>
{ //<-- This is the marked error by webpack
this.props. Foos.map( foo=>{
return < Foo key={foo.id} name={foo.name} surname={foo.surname}/>
})
}
)
}//end-render
}
This is the Foo class:
import React from 'react'
export default class Foo extends React.Component {
render() {
return <tr>
<td>{foo.name}</td>
<td>{foo.surname}</td>
</tr>
}
}
This is the main render:
render(){
if (this.state.foos.length > 0) {
console.log('Foos size ' + this.state.foos.length);
return <table>
<tbody>
<FooTable foos={this.state.foos}/>
</tbody>
</table>
} else {
return <p className="text-center">Loading Foos...</p>
}
}
Webpack marks an error in FooTable (Unexpected Token). It's marked by a comment.
you need to return single node from your component's (FooTable in this case )render method.
render() {
return(
<tr>
<td>id</td>
<td>name</td>
<td>surname</td>
</tr>
{ //<-- This breaks the single root
this.props.Foos.map( foo=>{
return < Foo key={foo.id} name={foo.name} surname={foo.surname}/>
})
}
)
}
you need to do sth like this :
render() {
return (
<tbody>
<tr>
<td>id</td>
<td>name</td>
<td>surname</td>
</tr>
{this.props.Foos.map(foo => (<Foo key={foo.id} name={foo.name} surname={foo.surname}/>))}
</tbody>)
}
The documentation says (see here) :
Note:
One limitation: React components can only render a single root
node. If you want to return multiple nodes they must be wrapped in a
single root.
You need to wrap your <tr> and your <Foo>elements in a single node, for example a <div>:
render() {
return(
<div>
<tr>
<td>id</td>
<td>name</td>
<td>surname</td>
</tr>
{ //<-- No more multiple roots
this.props.Foos.map( foo => {
return < Foo key={foo.id} name={foo.name} surname={foo.surname}/>
}
</div>
)
}
Hope this helps
Related
I want to add Button to the Component which after click will navigate to another page.
Currently I am using react 18.0.
Bellow is the component:
import React from 'react';
import EmployeeService from '../Services/EmployeeService';
import { AddEmployee } from '../Functions/AddEmployee';
class ListEmployeeComponent extends React.Component {
constructor(props) {
super(props)
this.state={
employees: []
}
}
componentDidMount() {
EmployeeService.getEmployees().then((res) => {
this.setState({employees:res.data});
});
}
render() {
return (
<div>
<h2 className='text-center'>Employee List</h2>
<div className='row'>
<button className='btn btn-primary' onClick={AddEmployee.bind(this)}>Add Employee</button>
</div>
<div className='row'>
<table className='table table-striped table-bordered'>
<thead>
<tr>
<th>Employee First Name</th>
<th>Employee Last Name</th>
<th>Employee Email Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
this.state.employees.map(
employee =>
<tr key={employee.id}>
<td>{employee.firstName}</td>
<td>{employee.lastName}</td>
<td>{employee.email}</td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
);
}
}
export default ListEmployeeComponent;
this is the button:
import { useNavigate } from 'react-router';
export function AddEmployee(a, b) {
let navigate = useNavigate();
return (
navigate('http://localhost:3000/add-employee')
);
}
And on the attached picture is an error which I am getting when I press button:
Erorr
As the error message says, React hooks need to be used from within a function component. The hook in question here is useNavigate, which you're calling from a regular function, hence the error. If you instead inject the navigate variable into the AddEmployee function, you shouldn't have a problem.
export function AddEmployee(navigate, a, b) {
navigate(...);
}
// then within the component, do something akin to
const navigate = useNavigate();
AddEmployee(navigate, a, b)
Okey after several hours of looking how to solve a problem I have made following
I removed Add Employee function complitely.
I imported Link from react-router-dom and change the Button to be Link to
import {React, Component} from 'react';
import {Link} from 'react-router-dom'
import EmployeeService from '../Services/EmployeeService';
class ListEmployeeComponent extends Component {
constructor(props) {
super(props)
this.state={
employees: []
}
}
componentDidMount() {
EmployeeService.getEmployees().then((res) => {
this.setState({employees:res.data});
});
}
render() {
return (
<div>
<h2 className='text-center'>Employee List</h2>
<div className='row'>
<Link to = '/add-employee' className='btn btn-primary' >Add Employee </Link>
</div>
<div className='row'>
<table className='table table-striped table-bordered'>
<thead>
<tr>
<th>Employee First Name</th>
<th>Employee Last Name</th>
<th>Employee Email Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
this.state.employees.map(
employee =>
<tr key={employee.id}>
<td>{employee.firstName}</td>
<td>{employee.lastName}</td>
<td>{employee.email}</td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
);
}
}
export default ListEmployeeComponent;
I'm trying to fill an array with a list of objects that comes from an api, the objects are coming normally, but when trying to move to the array and play in the v-for nothing appears.
Here's my data vars:
data() {
return {
elementsReport: [],
};
},
Here's my "computed" section:
computed: {
changeElements: {
get() {
return this.elementsReport;
},
set() {
return this.elementsReport;
}
}
}
Here's my api call:
this.elementsReport = this.getHistoryDeliveryPositionsByDriverIdAndDateAPI();
Here's my api function:
getHistoryDeliveryPositionsByDriverIdAndDateAPI() {
axios
.post("/web-api/reports/history-delivery-position/generate", {
driver_id: this.driver,
initial_date: this.initialDate,
final_date: this.finalDate
})
.then(({ data }) => {
_this.elementsReport = data;
})
.catch(function() {
alert("Erro ao filtrar relatórios");
});
}
Here's my html table with the v-for:
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
</tr>
</thead>
<tbody>
<tr v-for="elements in changeElements">
<td scope="row">{{elements.id}}</td>
<td></td>
</tr>
</tbody>
</table>
Have you tried to bind the key prop to the tr element?
Like this:
<tr v-for="elements in elementsReport" :key="elements.id">
<td scope="row">{{elements.id}}</td>
<td></td>
</tr>
Lots of things wrong with your code. I would recommend using tutorials to learn JavaScript and Vue.
1) There is no need for a computed here. Use elementsReport in the template.
<tr v-for="elements in elementsReport" :key="elements.id">
<td scope="row">{{elements.id}}</td>
<td></td>
</tr>
2) Your API function is wrong, and you are trying to set elementsReport twice. It should be:
getHistoryDeliveryPositionsByDriverIdAndDateAPI() {
return axios
.post("/web-api/reports/history-delivery-position/generate", {
driver_id: this.driver,
initial_date: this.initialDate,
final_date: this.finalDate
})
.then(({ data }) => {
return data;
})
.catch(function() {
alert("Erro ao filtrar relatórios");
});
}
3) Call it like:
this.getHistoryDeliveryPositionsByDriverIdAndDateAPI().then(data => {
this.elementsReport = data;
});
I am new to ReactJS,now working on small project. I am trying to load data from a JSON file,but I'm getting this "Syntax error: Unexpected token m in JSON at position 0 at JSON.parse ()". Thanks in advance.
Here is my code :
import React from 'react';
import dataa from './src/dataa.json';
class App extends React.Component {
constructor() {
super();
this.state = {
data:require('json!./dataa.json')
}
}
render() {
return (
<div>
<Header/>
<table>
<tbody>
{this.state.data.map((person, i) => <TableRow key={i} data={person} />)}
</tbody>
</table>
</div>
);
}
}
class TableRow extends React.Component {
render() {
return (
<tr>
<td>{this.props.data.id}</td>
<td>{this.props.data.name}</td>
<td>{this.props.data.age}</td>
</tr>
);
}
}
export default App;
and JSON data:
[{"id":"1","name":"Smith","age":"20"},
{"id":"2","name":"Jackson","age":"94"},
{"id":"3","name":"Doe","age":"80"},
{"id":"4","name":"Johnson","age":"37"}]
My App.jsx file is below.
import React from 'react';
class App extends React.Component {
constructor() {
super();
this.state = {
data:require('json!./dataa.json')
}
}
render() {
return (
<body>
<div>
<Header/>
<center>
<table>
<tr><th>NAME</th><th>VALUE</th><th>COLOR</th><th>Edit Table</th></tr>
<tbody>
{this.state.data.table.map(person, i) => <TableRow key = {i} data = {person} />)}
</tbody></table></center>
</div>
</body>
);
}
}
class Header extends React.Component {
render() {
return (
<div><center>
<h1>Creation of table from JSON</h1></center>
</div>
);
}
}
class TableRow extends React.Component {
render() {
return (
<tr>
<td>{this.props.data.NAME}</td>
<td>{this.props.data.VALUE}</td>
<td>{this.props.data.COLOR}</td>
<td contentEditable='true'></td>
</tr>
);
}
}
export default App;
and my dataa.json file is like below
[{"table":
[{"NAME":"Alan","VALUE":12,"COLOR":"blue"},
{"NAME":"Shan","VALUE":13,"COLOR":"green"},
{"NAME":"John","VALUE":45,"COLOR":"orange"},
{"NAME":"Minna","VALUE":27,"COLOR":"teal"}]
}]
Question: It is compiled fine. but it display error in browser "cannot read the property of map undefined".How to resolve
Note: but it works fine when the json file like,
[{"NAME":"Alan","VALUE":12,"COLOR":"blue"},
{"NAME":"Shan","VALUE":13,"COLOR":"green"},
{"NAME":"John","VALUE":45,"COLOR":"orange"},
{"NAME":"Minna","VALUE":27,"COLOR":"teal"}]
}]
this.state.data doesn't have property table, because it is an array of single object.
Correct JSON structure to this
{
"table": [
{"NAME":"Alan","VALUE":12,"COLOR":"blue"},
{"NAME":"Shan","VALUE":13,"COLOR":"green"},
{"NAME":"John","VALUE":45,"COLOR":"orange"},
{"NAME":"Minna","VALUE":27,"COLOR":"teal"}
]
}
and use this.state.data.table.map.
I am receiving json data from server and i am trying to access it individually using map function in front end but i am receiving an error as this.state.post.map is not a function. below is the code how do i overcome this.
import React from 'react';
import axios from 'axios';
//require('./style.scss');
class Premontessori extends React.Component{
constructor(props){
super(props);
this.state={
post:[]
};
}
componentDidMount(){
let self = this;
axios.get('http://localhost:8080/list')
.then(function(data) {
console.log(data);
self.setState({post:data});
});
}
render(){
return (
<div>
<table>
<tbody>
{
this.state.post.map(function(item, index){
return (
<tr>
<td>{item.Id}</td>
<td>{item.Name}</td>
<td>{item.Age}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
);
}
}
export default Premontessori;
From your comment,
'since this.state.post is not an array hence you get an error that map is not a function.
You need to map over the data in the post object like
<tbody>
{this.state.post.data.map(function(item, index) {
return (
<tr key={index}>
<td>{item.Id}</td>
<td>{item.Name}</td>
<td>{item.Age}</td>
</tr>
)
})
}
</tbody>
I think you have to make an adjustment in the code in the componentDidMount life-cycle method as shown below. This is because the response from the axios call is wrapping the array data, so you have to fetch that array and update your state if the status code is 200.
import React from 'react';
import axios from 'axios';
//require('./style.scss');
class Premontessori extends React.Component{
constructor(props){
super(props);
this.state={
post:[]
};
}
componentDidMount(){
let self = this;
axios.get('http://localhost:8080/list')
.then(function(res) {
console.log(res);
if(res.status === 200){
self.setState({post:res.data});
}
})
.catch(function(err){
console.log(err);
});
}
render(){
return (
<div>
<table>
<tbody>
{
this.state.post.map(function(item, index){
return (
<tr>
<td>{item.Id}</td>
<td>{item.Name}</td>
<td>{item.Age}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
);
}
}
export default Premontessori;