React Application does not display data fetched from MongoDB Atlas

505 Views Asked by At

I'm creating a simple web application (MERN stack) that fetches data from MongoDb Atlas. I have two components one is called Listings (an array of listing Items) and the other one is called ListingItem:

The Listings.js component:

import React, { Fragment, useContext, useEffect } from "react";

import ListingItem from "./ListingItem";
import ListingContext from "../../context/listing/listingContext";

const Listings = () => {
 const listingContext = useContext(ListingContext);

 const { listings, getListings, loading } = listingContext;

 useEffect(() => {
 getListings();
 // eslint-disable-next-line
 }, []);

 return (
 <Fragment>
   {listings.map((listing) => (
     <ListingItem key={listing._id} listing={listing} />
   ))}
 </Fragment>
 );
 };

export default Listings;

The ListingItem.js component:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import PropTypes from "prop-types";
import Card from "@material-ui/core/Card";
import CardHeader from "@material-ui/core/CardHeader";
import CardMedia from "@material-ui/core/CardMedia";
import CardContent from "@material-ui/core/CardContent";
import CardActions from "@material-ui/core/CardActions";
import Avatar from "@material-ui/core/Avatar";
import Typography from "@material-ui/core/Typography";
import IconButton from "@material-ui/core/IconButton";
import FavoriteIcon from "@material-ui/icons/Favorite";
import ShareIcon from "@material-ui/icons/Share";

import listingImage from "../../resources/listing.jpg";

const useStyles = makeStyles(() => ({
 root: {
  maxWidth: 345,
 },
 media: {
  height: 0,
  paddingTop: "56.25%", // 16:9
 },
 avatar: {
  backgroundColor: "coral",
 },
}));

const ListingItem = (listing) => {
  const classes = useStyles();

  const { neighbourhood, bedrooms, price, priceCurr, area, areaUoM } = listing;

  return (
   <div className="container">
    <div className="listing-item">
    
     <Card className={classes.root}>
       <CardHeader
         avatar={<Avatar className={classes.avatar} />}
         title="Title"
         subheader="Subtitle"
       />
       <CardMedia className={classes.media} image={listingImage} title="" />
       <CardContent>
        
        <Typography component="p">
          {price} {priceCurr}
        </Typography>
        <Typography component="p">A {bedrooms} bedroom,</Typography>
        <Typography component="p">
          {area} {areaUoM} apartment
        </Typography>
        <Typography component="p">Located in {neighbourhood}</Typography>
      </CardContent>
      <CardActions disableSpacing>
        <IconButton aria-label="add to favorites">
          <FavoriteIcon />
        </IconButton>
        <IconButton aria-label="share">
          <ShareIcon />
        </IconButton>
      </CardActions>
    </Card>
  </div>
</div>
);
};

ListingItem.propTypes = {
 listing: PropTypes.object.isRequired,
};

export default ListingItem;

The App is obviously connected to the Mongodb Atlas, because when I run the app, it renders exactly two Listing Items to the screen (I have two documents in the database). But it does not display the variables {price}, {priceCurr}, {bedrooms} and {neighbourhood} which I have in ListingItem Component.

Is there anybody who has experienced the same issue?

2

There are 2 best solutions below

0
On BEST ANSWER

Try this to display the data present in listings. First of all console it before returning the listings to ListingItem and if it do not contains any data then there might be different object structure or might be empty.

After it really contains the data then try this:

 const Listings = () => {
 const listingContext = useContext(ListingContext);

 const { listings, getListings, loading } = listingContext;

 useEffect(() => {
 getListings();
 // eslint-disable-next-line
 }, []);

 return (
 <Fragment>  //Try passing whole object of **listings**
     <ListingItem key={listing._id} listing={listings} />
 </Fragment>
 );
 };

export default Listings;

After that in ListingItem Component try this:

    const ListingItem = (props) => {
      const classes = useStyles();
        
      return (
        
       props && props.listing.map(item=>{ //Apply map after checking props
        <div className="container">
        <div className="listing-item">
        
         <Card className={classes.root}>
           <CardHeader
             avatar={<Avatar className={classes.avatar} />}
             title="Title"
             subheader="Subtitle"
           />
           <CardMedia className={classes.media} image={listingImage} title="" />
           <CardContent>
            
            <Typography component="p">
              {item.price} {item.priceCurr}
            </Typography>
            <Typography component="p">A {item.bedrooms} bedroom,</Typography>
            <Typography component="p">
              {item.area} {item.areaUoM} apartment
            </Typography>
            <Typography component="p">Located in {item.neighbourhood}</Typography>
          </CardContent>
          <CardActions disableSpacing>
            <IconButton aria-label="add to favorites">
              <FavoriteIcon />
            </IconButton>
            <IconButton aria-label="share">
              <ShareIcon />
            </IconButton>
          </CardActions>
        </Card>
      </div>
    </div>
     }) 
    );
    };

Second way is to access it after destructuring of props

So, In your ListingItem Component access listing like this:

const {neighbourhood, bedrooms, price, priceCurr, area, areaUoM }= listing.listing;

And it will access it properly.

0
On

I think you have done wrong destructuring of props.

<ListingItem key={listing._id} listing={listing} />

const ListingItem = ({listing}) => {

Wrap your props inside a {}