WyoMonkey
WyoMonkey

Reputation: 241

Image not loading when mapping Material-UI cards

I am kind of new to react, and this is the first time trying to take information from an API call, mapping through it, and making a Material-UI card for each response. When I make a single card, it comes out fine. When I map through the response, cards are made for each response, and text is entered into the fields correctly, but the image doesn't load. Even when using a static image not loaded from the response, the image doesn't show. Here is what I'm looking at:

//calls API, maps results, and builds cards

import React, {Component} from 'react'


import Request from 'superagent'
import Grid from '@material-ui/core/Grid'
import Cards from './cards'


const url = "http://localhost:4000/products"
const get = Request.get(url)

class ProductList extends Component {
    state = {
        products: []

    }

    constructor() {
        super()
        this.getProducts()
    }

    getProducts = () =>

    Request.get(url)
    .then((response) => {
        const prods = (response.body.products)
        console.log(prods)
        this.setState({products: prods})
    })

render() {
    return (
    <div>
        {this.state.products ? (

            <Grid container spacing={24} style = {{padding: 24}}>
            { this.state.products.map(prods => (
                <Grid item xs={8} sm={4} lg={4} xl={3}>
                 <Cards id={prods.id} name = {prods.name} quantity = {prods.quantity} price = {prods.price} image = {prods.iamge} />
                </Grid>

                ))}
            </Grid>
            ) : "No products found" }
    </div>
        )   
}

}


export default ProductList;

//builds cards

import React from 'react'


import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import Request from 'superagent';


const styles = {
  card: {
    maxWidth: 345,
  },
  media: {
    height: 0,
    paddingTop: '56.25%', // 16:9
  },
};

const Cards = (props) => {
    return(

        <div>
      <Card>
        <CardMedia
          image= {require ("./images/matcha.jpg")}
          title="{props.name}"
        />
        <CardContent>
          <Typography gutterBottom variant="headline" component="h2">
            {props.name}
          </Typography>
          <Typography component="p">
           {props.price}
          </Typography>
        </CardContent>
        <CardActions>
          <Button size="small" color="primary">
            Share
          </Button>
          <Button size="small" color="primary">
            Learn More
          </Button>
        </CardActions>
      </Card>
    </div>
  );


Cards.propTypes = {
  classes: PropTypes.object.isRequired,
}


}

export default Cards

//builds an individual card

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import Request from 'superagent';

const styles = {
  card: {
    maxWidth: 345,
  },
  media: {
    height: 0,
    paddingTop: '56.25%', // 16:9
  },
};

function SimpleMediaCard(props) {
  const url = "http://localhost:4000/products";
  const { classes } = props;
  return (
    <div>
      <Card className={classes.card}>
        <CardMedia
          className={classes.media}
          image= {require ("./images/matcha.jpg")}
          title="Contemplative Reptile"
        />
        <CardContent>
          <Typography gutterBottom variant="headline" component="h2">
            Lizard
          </Typography>
          <Typography component="p">
            Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging
            across all continents except Antarctica
          </Typography>
        </CardContent>
        <CardActions>
          <Button size="small" color="primary">
            Share
          </Button>
          <Button size="small" color="primary">
            Learn More
          </Button>
        </CardActions>
      </Card>
    </div>
  );
}

SimpleMediaCard.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(SimpleMediaCard);

//renders page

import React from 'react'

import PropTypes from 'prop-types'
import { withStyles } from '@material-ui/core/styles'
import Card from '@material-ui/core/Card'
import CardActions from '@material-ui/core/CardActions'
import CardContent from '@material-ui/core/CardContent'
import CardMedia from '@material-ui/core/CardMedia'
import Button from '@material-ui/core/Button'
import Typography from '@material-ui/core/Typography'
import MenuBar from '../menubar'
import SimpleMediaCard from '../card'
import ProductList from '../productList'




function Products (props) {
    return (
        <div>
        <MenuBar />
        <SimpleMediaCard />
        <ProductList />
        </div>

        )
}

export default Products

On the rendered page there are four cards. The first one is as it should be, picture and text included. The next three cards (there are three items in the database) show text but no images. I thought at first I was having an issue with webpack and the need for 'require', but even when using the static image link, still no image. Any ideas?

Upvotes: 6

Views: 18104

Answers (5)

Luqman
Luqman

Reputation: 139

Since CardMedia is a generic component for rendering different types of media, providing the source src alone isn't enough. The component prop should be used to tell CardMedia what to render

import image from '../path/to/images/imageName.jpg'
...
...
<CardMedia component="img" src={image}

Upvotes: 12

Dorje Kirsten
Dorje Kirsten

Reputation: 1

If you are using Firebase Storage, do the following:

<CardMedia 
    className={classes.media}
    component="img"   
    src={collection.docId.downloadUrl}
    title="Whatever"
/>

Upvotes: 0

gayan ranasinghe
gayan ranasinghe

Reputation: 186

Adding this in case some one needed dynamic image loading with material UI Card component

note the use of require.context for import path and the template literals for image variable

const img = require.context('assets/img', true);

<CardMedia 
   className={classes.media}
   image={img(`./${imgSrc}`)}
   title='description goes..'
/>

Upvotes: 0

Praveen Aanand
Praveen Aanand

Reputation: 117

This work for me

import img from "./img/placeholder2.jpg";


 <CardMedia
          className={classes.media}
          image= {img}
          title="plcae holder"
        />

Upvotes: 5

WyoMonkey
WyoMonkey

Reputation: 241

After a day and a half of searching, the initial fix is pretty simple. CardMedia requires a height property in order to render an image. Adding

    <CardMedia style = {{ height: 0, paddingTop: '56%'}}
     image= {require ("./images/matcha.jpg")

at least rendered the static images. Hope this helps someone!

Upvotes: 18

Related Questions