Reputation: 3139
I have this JSON file:
export const IMAGE_GALLERY =
[
{
id: 0,
name: 'A nice house',
image:'assets/images/aristi_1.jpg',
description: 'A beautiful house. The owner is lucky!',
comments: [
{
id: 0,
rating: 5,
comment: "A magnificent view",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 1,
rating: 4,
comment: "I wish I could stay there for a few days",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 2,
rating: 4,
comment: "Beautiful garden",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 3,
rating: 4,
comment: "My dream home",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 4,
rating: 4,
comment: "Magnificent architecture",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
},
]
},
{
id: 1,
name: 'Vikos Canyon',
image:'assets/images/aristi_2.jpg',
description: 'A magnificent view of Vikos Canyon',
comments: [
{
id: 0,
rating: 5,
comment: "Wonderful!",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 1,
rating: 4,
comment: "Splendid",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 2,
rating: 3,
comment: "Beautiful garden",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 3,
rating: 4,
comment: "Nice architecture!",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 4,
rating: 2,
comment: "Wow!",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
}
]
},
{
id: 2,
name: 'Central square',
image:'assets/images/aristi_3.jpg',
description: 'The center of Aristi',
comments: [
{
id: 0,
rating: 5,
comment: "Wonderful square",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 1,
rating: 4,
comment: "I indeed love aristi",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 2,
rating: 3,
comment: "Splendid!",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 3,
rating: 4,
comment: "I am speechless!",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 4,
rating: 2,
comment: "I was there it was amazing!",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
}
]
},
{
id: 3,
name: 'Central square',
image:'assets/images/aristi_4.jpg',
description: 'Another view of the village\'s center',
comments: [
{
id: 0,
rating: 5,
comment: "Imagine all the eatables, living in conFusion!",
author: "John Lemon",
date: "2012-10-16T17:57:28.556094Z"
},
{
id: 1,
rating: 4,
comment: "Sends anyone to heaven, I wish I could get my mother-in-law to eat it!",
author: "Paul McVites",
date: "2014-09-05T17:57:28.556094Z"
},
{
id: 2,
rating: 3,
comment: "Eat it, just eat it!",
author: "Michael Jaikishan",
date: "2015-02-13T17:57:28.556094Z"
},
{
id: 3,
rating: 4,
comment: "Ultimate, Reaching for the stars!",
author: "Ringo Starry",
date: "2013-12-02T17:57:28.556094Z"
},
{
id: 4,
rating: 2,
comment: "It's your birthday, we're gonna party!",
author: "25 Cent",
date: "2011-12-02T17:57:28.556094Z"
}
]
},
{
id: 4,
name: 'A wonderful image.',
image:'assets/images/aristi_5.jpg',
description: 'A green paradise before Easter Day',
comments: []
},
{
id: 5,
name: 'From the camera of a drone',
image:'assets/images/aristi_6.jpg',
description: 'An overview of the village from the camera of a drone',
comments: []
},
{
id: 6,
name: 'Aristi Resort',
image:'assets/images/aristi_7.jpg',
description: 'The Aristi Resort hotel',
comments: []
},
{
id: 7,
name: 'Elias Guest House',
image:'assets/images/aristi_8.jpg',
description: 'The Guest House Elias',
comments: []
},
]
and want to render some of its elements.
So here is my main component.
import React from 'react';
import { Navbar, NavbarBrand } from 'reactstrap';
import Gallery from './components/GalleryComponent';
import { IMAGE_GALLERY } from "./shared/image_gallery";
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
image_gallery: IMAGE_GALLERY
}
}
render() {
return (
<div className="App">
<Navbar style={{backgroundColor: '#378248'}}>
<div className="container">
<NavbarBrand style={{color: '#fff'}} href="/">I love Aristi</NavbarBrand>
</div>
</Navbar>
<Gallery image_gallery={this.state.image_gallery} />
</div>
);
}
}
export default App;
As you can see I am setting the IMAGE_GALLERY
array as the state of my component. Next, I am passing this state down (as props) to the Gallery
component.
import React, { Component } from 'react';
import { Card, CardImg, CardImgOverlay, CardText, CardBody, CardTitle } from 'reactstrap';
import GalleryDetail from './GalleryDetailComponent';
class Gallery extends Component {
constructor(props) {
super(props)
this.state = {
selectedImage: null
}
}
onDishSelect(gallery) {
this.setState({
selectedImage: gallery
})
}
render() {
const gallery = this.props.image_gallery.map((gallery) => {
return (
<div key={gallery.id} className="col-12 col-md-5">
<Card onClick={() => this.onDishSelect(gallery)}>
<CardImg width="100%" src={gallery.image} alt={gallery.name}/>
<CardImgOverlay body className="ml-5" style={{
position: 'absolute',
right: '45px',
}}>
<CardTitle style={{
backgroundColor: '#378248',
color:"#fff",
textAlign: 'center',
border: '1px solid black' }}>{gallery.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
)
})
return (
<div className="container">
<div className="row">
{gallery}
</div>
<GalleryDetail gallery_image={this.state.selectedImage} />
</div>
);
}
}
export default Gallery;
I can display the images with the appropriate title on top of them. Now when I click an image, I want to display again the image, its title, description, and comments. To do that I am passing down the state to another Component
called GalleryDetail
.
import React, { Component } from 'react';
import { Card, CardImg, CardText, CardBody, CardTitle } from 'reactstrap';
class GalleryDetail extends Component {
convertDateToCommentDateFormat(timestamp) {
const date = new Date(timestamp);
return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' });
}
renderImage(gallery){
if(gallery !== null) {
return (
<Card>
<CardImg withd="100%" src={gallery.image} alt={gallery.name}></CardImg>
<CardBody>
<CardTitle><h3>{gallery.name}</h3></CardTitle>
<CardText>{gallery.description}</CardText>
</CardBody>
</Card>
)
} else {
return (
<div>
</div>
)
}
}
renderComments(comments) {
if (comments == null || comments.length === 0) {
return (
<div></div>
);
}
const renderedComments = comments.map((comment) => {
return (
<li>
<p>{comment.comment}</p>
<p>-- {comment.author}, {this.convertDateToCommentDateFormat(comment.date)}</p>
</li>
);
});
return (
<div>
<h4>Comments</h4>
<ul className="list-unstyled">
{ renderedComments }
</ul>
</div>
);
}
render() {
return(
<div class="row">
<div className="col-12 col-md-5 m-1">
{ this.renderImage(this.props.gallery_image) }
</div>
<div className="col-12 col-md-5 m-1">
{ this.renderComments(this.props.gallery_image.comments) }
</div>
</div>
)
}
}
export default GalleryDetail;
I can read everything apart from the comment. I am getting
Uncaught TypeError: Cannot read property 'comments' of null
in
{ this.renderComments(this.props.gallery_image.comments) }
Did I miss something? Why can't I read the comments?
Thanks, Theo.
Upvotes: 0
Views: 68
Reputation: 15166
You need to handle the null
check earlier like the following:
{ this.renderComments(this.props.gallery_image ? this.props.gallery_image.comments : null) }
It failed earlier, technically it means comments
does not exists on null
. So you need to check first if this.props.gallery_image
has any value.
Upvotes: 1