Reputation:
I want to retrieve a list of Companies on a page. I consoled the incoming data just to be sure and it looks as follows
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": "56407787-472f-44c9-b726-189798c7e217",
"address": {
"street": "test street",
"postcode": "test 12",
"city": "test city",
"country": "test country"
},
"contact_name": "Angy",
"contact_phone": "33333333",
"contact_email": "[email protected]",
}
The following component creates a list
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import IconButton from '@material-ui/core/IconButton';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import EditIcon from '@material-ui/icons/Edit';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
maxWidth: 752,
},
demo: {
backgroundColor: theme.palette.background.paper,
},
title: {
margin: theme.spacing(4, 0, 2),
},
}));
function generate(props) {
return props.data.results.map((com) =>
<ListItem key={com.id}>
<ListItemText primary={com.name}/>
<IconButton edge="end" aria-label="edit">
<EditIcon />
</IconButton>
</ListItem>
)}
const Company = (props) => {
const classes = useStyles();
// console.log('data is ', props.data.results)
return (
<div className={classes.root}>
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
<Typography variant="h6" className={classes.title}>
company list
</Typography>
<div className={classes.demo}>
<List> {generate(props)} </List>
</div>
</Grid>
</Grid>
</div>
);
};
export default Company;
The following component renders the list:
import React from "react";
import axios from 'axios';
import Company from "./Company";
class CompanyList extends React.Component {
state = {
companies: []
}
componentDidMount() {
axios.get('http://127.0.0.1:8000/companies')
.then(res => {
this.setState({
companies: res.data
});
console.log(res.data)
})
}
render() {
return (
<Company data={this.state.companies}/>
)
}
}
export default CompanyList;
I receive an error as
TypeError: Cannot read property 'map' of undefined
I am new to ReactJS, and presumably stuck with this error. What am I doing wrong here?
Upvotes: 0
Views: 64
Reputation: 2517
Like what you're seeing, it's initially an empty array on first render than a nested dict (aka object) in your second render, but you're handling like it'll just be a nested object.
I do not know what exactly you need (rendering an empty list, not rendering a list at all, passing an object/array, etc.). Here is simple fix you can do so props.data
is always a defined nested object:
class CompanyList extends React.Component {
state = {
companies: { results: [] }
}
// ...
Upvotes: 0
Reputation: 342
Your initial state has companies
which is an empty array and your res.data
is an object. Initially, there is no results
in an empty array. Due to asynchronous call, you should check if results
exists. This (props.data.results||[])
might solve your problem. Basically it says if there is results
use it else use an empty array.
Upvotes: 1
Reputation: 683
You are not passing the state to the child that needs to use the companies data (so from the CompanyList component to your Company function https://reactjs.org/docs/state-and-lifecycle.html
Either use state management (Redux for instance) to link your Company props to the CompanyList state, or create a Context and combine with the useContext hook https://reactjs.org/docs/hooks-reference.html#usecontext
Upvotes: 0