In react, I can set a variable within a component, but I am having a hard time setting var data = {} within just a regular JavaScript file - list.js
I retrieve my data using Axios, but data.map is undefined, but the data is not undefined, as seen in the console. I am assuming that this is because data.map is being called before data has been retrieved from the Axios.get. The reason why I say this, is because when I do a console.log(data), I can see the data in the console:
import React from 'react';
import Axios from 'axios';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';
var data = {};
function componentDidMount() {
Axios.get('http://localhost/api/get-coins/')
.then(
responseJson => {
data = JSON.parse(JSON.stringify(responseJson.data));
// console.log(data);
return data;
}
)
.catch(
error => console.log(error)
)
}
function SimpleTable(props) {
const { classes } = props;
data = componentDidMount();
console.log(data);
return (
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell numeric>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell numeric>Price</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(n => {
return (
<TableRow key={n.id}>
<TableCell component="th" scope="row">
{n.name}
</TableCell>
<TableCell numeric>{n.price}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Paper>
);
}
SimpleTable.propTypes = {
classes: PropTypes.object.isRequired,
};
How can I retrieve the data first, followed by calling the SimpleTable prototype?
I have tried the following, with a setTimeout, but I receive an error that null was returned, but again, I see the data in the console:
function SimpleTable(props) {
var data = {};
const { classes } = props;
data = Axios.get('http://local.sites/ng6crud/api/get-coins/')
.then(
responseJson => {
data = JSON.parse(JSON.stringify(responseJson.data));
console.log(data);
setTimeout(function () {
return (
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell numeric>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell numeric>Price</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(n => {
return (
<TableRow key={n.id}>
<TableCell component="th" scope="row">
{n.name}
</TableCell>
<TableCell numeric>{n.price}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Paper>
);
}, 1000);
}
)
.catch(
error => console.log(error)
);
}
I feel like with React, I am fighting every step of the way. Please help and thanks in advance
Edit: Thanks to @guillaume answer. I was able to make it work. I want to point out that I was trying to do this without creating a class or component, but I guess there is no way to have the data in time before the render occurs.
import React from 'react';
import Axios from 'axios';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';
class List extends React.Component {
constructor(props) {
super(props);
this.state = {data: []}
}
componentDidMount() {
Axios.get('http://localhost/api/get-coins/')
.then(
responseJson => {
this.setState({
data: JSON.parse(JSON.stringify(responseJson.data))
});
return this.state.data;
}
)
.catch(
error => console.log(error)
)
}
render() {
return (
<Paper>
<Table>
<TableHead>
<TableRow>
<TableCell numeric>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell numeric>Price</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.data.map(n => {
return (
<TableRow key={n.id}>
<TableCell component="th" scope="row">
{n.id}
</TableCell>
<TableCell component="th" scope="row">
{n.name}
</TableCell>
<TableCell numeric>{n.price}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Paper>
);
}
}
export default List
You can't use React lifecycle methods inside a functional component unless you use react-pure-lifecycle .
Currently, your function componentDidMount is just that: a function you defined yourself. it does not behave the way React's componentDidMount method does.
You need to use a class component to use this method:
class SimpleTable extends React.Component {
constructor(props) {
super(props);
this.state = {data: []}
}
componentDidMount() {
Axios.get('http://localhost/api/get-coins/')
.then(
responseJson => {
this.setState({
data: JSON.parse(JSON.stringify(responseJson.data));
});
return data;
}
)
.catch(
error => console.log(error)
)
}
render() {
const { classes } = props;
return (
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell numeric>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell numeric>Price</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map(n => {
return (
<TableRow key={n.id}>
<TableCell component="th" scope="row">
{n.name}
</TableCell>
<TableCell numeric>{n.price}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Paper>
);
}
}
map
is a method of Arrays but you initialise your data to an Object. Do var data = [];
and your component will successfuly call .map
on the empty array and render an empty table. Re-render your component when the data is ready and then the table will be filled.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.