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?
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!
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}
This work for me
import img from "./img/placeholder2.jpg";
<CardMedia
className={classes.media}
image= {img}
title="plcae holder"
/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With