react-grid-gallery component doesn't work - javascript

I want to create simple image gallery with lightbox modals. I found this library and copied example source, but it doesn't work. <Gallery images={IMAGES}/> gives nothing, iterraly nothing is displayed in browser.
Its my code:
import React, {Component} from 'react';
import './placeDetails.css'
/* Importing axois */
import axios from 'axios';
/* Importing animations */
import Fade from 'react-reveal/Fade';
/* Importing gallery library */
import Gallery from 'react-grid-gallery';
export default class placeDetails extends Component {
getInitialState(){
/* Getting data from api */
this.GetDetailsFromApi();
}
constructor(props) {
super(props);
this.state ={
data: "initial_value",
ReviewsVisible: false,
GalleryShown: false,
}
}
/* This function handles clicks of reviews header */
ReviewsHeaderClick() {
let value = this.state.ReviewsVisible;
this.setState({
ReviewsVisible: !value
})
}
GalleryHeaderClick(){
let value = this.state.GalleryShown;
this.setState({
GalleryShown: !value
})
this.GetGalleryLinks();
}
GetGalleryLinks(){
/* Getting ID of requested place */
let place_id = localStorage.getItem('SelectedPlaceID');
/* Setting up URL */
let url = "http://localhost:8000/api/image_gallery/"+place_id;
/* Requesting my backend to get images links list */
/* Requesting my backend */
axios({
method: 'get',
url: url,
headers: {
"content-type": "application/json"
}
}).then((response) => {
/* Getting data */
let data = response.data[0].json_data;
let final_data = [];
for (var i = 0; i < data.length; i++) {
//console.log(data[i]);
/* Every photo will be represented by one object with various propeties */
let object = new Object();
/* Setting propeties under names that are compatible with "react-grid-gallery" library */
object.src = data[i].img_url;
object.thumbnailWidth = data[i].width;
object.thumbnailHeight = data[i].height;
object.thumbnail = data[i].img_url;
final_data.push(object);
}
console.log(final_data)
/* Sending got data to sessionStorage as JSON string, and setting details to correct one */
localStorage.setItem("place_gallery_data", JSON.stringify(final_data));
}).catch(function (error) {
console.log(error)
});
this.forceUpdate()
}
render() {
/* Setting data */
let data = JSON.parse(localStorage.getItem("place_details_data"));
let images = JSON.parse(localStorage.getItem("place_gallery_data"));
console.log(images);
const IMAGES =
[{
src: "https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg",
thumbnail: "https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_n.jpg",
thumbnailWidth: 320,
thumbnailHeight: 174,
isSelected: true,
caption: "After Rain (Jeshu John - designerspics.com)"
},
{
src: "https://c2.staticflickr.com/9/8356/28897120681_3b2c0f43e0_b.jpg",
thumbnail: "https://c2.staticflickr.com/9/8356/28897120681_3b2c0f43e0_n.jpg",
thumbnailWidth: 320,
thumbnailHeight: 212,
tags: [{value: "Ocean", title: "Ocean"}, {value: "People", title: "People"}],
caption: "Boats (Jeshu John - designerspics.com)"
},
{
src: "https://c4.staticflickr.com/9/8887/28897124891_98c4fdd82b_b.jpg",
thumbnail: "https://c4.staticflickr.com/9/8887/28897124891_98c4fdd82b_n.jpg",
thumbnailWidth: 320,
thumbnailHeight: 212
}]
/* This function returns html with reviews */
function Reviews(props) {
const content = props.reviews.map((review) =>
<div key={review.id} className="mt-5">
<header>
<h4 id={review.place_id} onClick={review.getComponent}> {review.name} </h4>
</header>
<div className="info mt-3 px-4">
{review.author_name} <br/>
<div className="mt-2"> {review.text} </div> <br/>
<div> <b>Rating:</b> {review.rating} </div> <br/>
</div>
</div>
);
return (
<div>
{content}
</div>
);
}
return (
<div className="place_details_component">
<div className="containter">
<div className="row">
<div className="spacer col-1"></div>
<header className="col-10 p-3 py-5">
<h2> Details of
<div className="place_name"> {data.name}!</div>
</h2>
</header>
<div className="spacer col-1"></div>
Back to places list!
Back to home!
<div className="col-12"> <b>Address:</b> {data.vicinity} </div>
<div className="col-12"> <b>Website:</b> {data.website} </div>
<div className="col-12"> <b>Phone:</b> {data.formatted_phone_number} </div>
<div className="col-12 mb-5"> <b>Excat address:</b> {data.formatted_address} </div>
<div className="col-12"> <b>Rating:</b> {data.rating} </div>
<div className="col-12"> <b>Number of ratings:</b> {data.user_ratings_total} </div>
<div className="col-12" onClick={this.ReviewsHeaderClick.bind(this)}>
<b>Reviews:</b>
{ this.state.ReviewsVisible && <span className="up_arrow"> ▲ </span> }
{ !this.state.ReviewsVisible && <span className="dropdown_arrow"> ▼ </span> }
</div>
<Fade when={this.state.ReviewsVisible}>
{ this.state.ReviewsVisible &&
<Reviews reviews={data.reviews} className="" getComponent={this.getComponent}/>
}
</Fade>
<header className="col-12 mt-5 px-5" onClick={this.GalleryHeaderClick.bind(this)}>
<span className="gallery_header"> Photos linked with this place: </span>
{ this.state.GalleryShown && <span className="up_arrow"> ▲ </span> }
{ !this.state.GalleryShown && <span className="dropdown_arrow"> ▼ </span> }
</header>
<Fade when={this.state.GalleryShown}>
</Fade>
<Gallery images={IMAGES}/>
</div>
</div>
</div>
);
}
}
I am sure I am missing something obvious but I can't find it myself.

Related

Passing a json value to another react component

I have a parent functional component named Dashboard and a child class component named DashboardTable. I'm making a graphql call in the parent class and want to pass the result into the child like this <DashboardTable data={opportunityData}/>.
problem: I can get see the data in the parent but its not showing in the child
Here is my code. Please let me know what I'm doing wrong
Dashboard
import React, { useEffect, useState } from "react";
import "bootstrap/js/src/collapse.js";
import DashboardTable from "../DashboardTable";
import { API } from "#aws-amplify/api";
import config from "../../aws-exports";
import * as queries from "../../graphql/queries";
export default function Dashboard() {
API.configure(config);
async function asyncCall() {
const gqlreturn = await API.graphql({
query: queries.listMockOppsTables,
});
//console.log(gqlreturn.data.listMockOppsTables); // result: { "data": { "listTodos": { "items": [/* ..... */] } } }
return gqlreturn;
}
const [opportunityTable, changeOpportunityTable] = useState(asyncCall());
console.log(opportunityTable); // this works! returns a promise
return (
<div>
<section className="py-5 mt-5">
<div className="container py-5">
<h2 className="fw-bold text-center">
Your upcoming shadowing events
<br />
<br />
</h2>
<DashboardTable data={opportunityTable}></DashboardTable>
</div>
</section>
</div>
);
}
DashboardTable
import React from "react";
import "bootstrap/js/src/collapse.js";
import Navigation from "../Navigation";
import { Link } from "react-router-dom";
import { API } from "#aws-amplify/api";
import config from "../../aws-exports";
import * as queries from "../../graphql/queries";
export class DashboardTable extends React.Component {
constructor() {
super();
this.state = {
opportunityData: this.props,
};
}
render() {
console.log(this.opportunityData); // this doesnt work :( no data
return (
<div>
<div
className="row row-cols-1 row-cols-md-2 mx-auto"
style={{ maxWidth: 900 }}
>
{this.opportunityData.map((opportunity) => (
<div className="col mb-4">
<div>
<a href="#">
<img
className="rounded img-fluid shadow w-100 fit-cover"
src="assets/img/products/awsLogo.jpg"
style={{
height: 250,
}}
/>
</a>
<div className="py-4">
<span
className="badge mb-2"
style={{ margin: 2, backgroundColor: "#ff9900" }}
>
{opportunity.interview_type}
</span>
<span
className="badge bg mb-2"
style={{ margin: 2, backgroundColor: "#ff9900" }}
>
{opportunity.level}
</span>
<span
className="badge bg mb-2"
style={{ margin: 2, backgroundColor: "#ff9900" }}
>
{opportunity.ShadowReverse}
</span>
</div>
</div>
</div>
))}
</div>
</div>
);
}
}
export default DashboardTable;
Few pointers
Call api on mount in parent's useEffect
In child directly use the passed property in child
function Dashboard() {
API.configure(config);
async function asyncCall() {
const gqlreturn = await API.graphql({
query: queries.listMockOppsTables,
});
//console.log(gqlreturn.data.listMockOppsTables); // result: { "data": { "listTodos": { "items": [/* ..... */] } } }
return gqlreturn;
}
// initialize with empty array
const [opportunityTable, changeOpportunityTable] = useState([]);
console.log(opportunityTable); // this works! returns a promise
// call api to fetch data on mount
useEffect(( => {
const fetchData = async () => {
const response = await asyncCall();
changeOpportunityTable(response)
}
fetchData()
}, [])
return (
<div>
<section className="py-5 mt-5">
<div className="container py-5">
<h2 className="fw-bold text-center">
Your upcoming shadowing events
<br />
<br />
</h2>
<DashboardTable data={opportunityTable}></DashboardTable>
</div>
</section>
</div>
);
}
class DashboardTable extends React.Component {
constructor() {
super();
//this.state = {
// opportunityData: this.props,
//};
}
render() {
console.log(this.props.data); // this doesnt work :( no data
return (
<div>
<div
className="row row-cols-1 row-cols-md-2 mx-auto"
style={{ maxWidth: 900 }}
>
//map thru data prop {this.props.data?.map((opportunity) => (
<div className="col mb-4">
<div>
<a href="#">
<img
className="rounded img-fluid shadow w-100 fit-cover"
src="assets/img/products/awsLogo.jpg"
style={{
height: 250,
}}
/>
</a>
<div className="py-4">
<span
className="badge mb-2"
style={{ margin: 2, backgroundColor: "#ff9900" }}
>
{opportunity.interview_type}
</span>
<span
className="badge bg mb-2"
style={{ margin: 2, backgroundColor: "#ff9900" }}
>
{opportunity.level}
</span>
<span
className="badge bg mb-2"
style={{ margin: 2, backgroundColor: "#ff9900" }}
>
{opportunity.ShadowReverse}
</span>
</div>
</div>
</div>
))}
</div>
</div>
);
}
}
Hope it helps
There are some bugs in the child like this.state.opportunityData = this.props, that end part should likely be this.props.opportunityData, however to get you going with the async call in the parent component give this a try
const [opportunityTable, changeOpportunityTable] = useState([]);
async function asyncCall() {
const gqlreturn = await API.graphql({
query: queries.listMockOppsTables,
});
changeOpportunityTable(gqlreturn);
}
useEffect(() => asyncCall(), []);

How to fix Error: Element type is invalid: expected a string or a class/function but got: undefined?

I have the above error message and i am not sure about what cause this to happen.
On the below code snippet i am fetching some data from a file named Data.js located on my root folder.
When i run my the app i receive the mentioned error message but when use the same data without importing for an external file it works perfectly. which is not making much sense, Can someone tells me what i am doing wrong please? Thanks in advance.
Services.js
import { FaCircle, FaShoppingCart, FaLaptop, FaLock } from 'react-icons/fa'
import { serviceLinks } from '../../../Data'
const data = serviceLinks;
console.log(data);
// const serviceLinks = [
// {
// title:'Haircut',
// text:'All dependencies are kept current to keep things fresh.'
// },
// {
// title:'Barberos',
// text:'You can use this design as is, or you can make changes!'
// },
// {
// title:'Color',
// text:'Is it really open source if its not made with love?'
// },
// ]
const icons = [
FaShoppingCart, FaLaptop, FaLock
]
function Services () {
return (
<section className="page-section" id="services">
<div className="container">
<div className="text-center">
<h2 className="section-heading text-uppercase">Services</h2>
<h3 className="section-subheading text-muted">Lorem ipsum dolor sit amet consectetur.</h3>
</div>
<div className="row text-center">
{ data.map((service,idx) => {
const Icon = icons[idx];
console.log(Icon)
return (
<div className="col-md-4" key={idx}>
<span className="fa-stack fa-4x">
<FaCircle className="svg-inline--fa fa-circle w-16 fa-stack-2x text-dark" height={100} width={100} />
<Icon className="svg-inline--fa fa-shopping-cart fa-w-18 fa-stack-1x fa-inverse" fill="white" />
</span>
<h4 className="my-3">{service.title}</h4>
<p className="text-muted">{service.text}</p>
</div>
)
})
}
</div>
</div>
</section>
)
}
export default Services;
data.js
const galleryLinks = [
{
title:'HairStyle',
haircutName:'Afro',
imgUrl:"assets/img/portfolio/fullsize/dr.cut_thebarbers_afro.jpg",
imgUrl2:"assets/img/portfolio/thumbnails/dr.cut_thebarbers_afro.jpg",
},
{
title:'Hairstyle',
haircutName:'Blondo',
imgUrl:"assets/img/portfolio/fullsize/dr.cut_thebarbers_blondo.jpg",
imgUrl2:"assets/img/portfolio/thumbnails/dr.cut_thebarbers_blondo.jpg",
},
{
title:'Hairstyle',
haircutName:'Chica',
imgUrl:"assets/img/portfolio/fullsize/dr.cut_thebarbers_chica.jpg",
imgUrl2:"assets/img/portfolio/thumbnails/dr.cut_thebarbers_chica.jpg",
},
{
title:'Hairstyle',
haircutName:'Nino',
imgUrl:"assets/img/portfolio/fullsize/dr.cut_thebarbershow_nino.jpg",
imgUrl2:"assets/img/portfolio/thumbnails/dr.cut_thebarbershow_nino.jpg",
},
{
title:'HairStyle',
haircutName:'Wavy',
imgUrl:"assets/img/portfolio/fullsize/dr.cut_thebarbershow_wavy.jpg",
imgUrl2:"assets/img/portfolio/thumbnails/dr.cut_thebarbershow_wavy.jpg",
},
{
title:'HairStyle',
haircutName:'Blondo2',
imgUrl:"assets/img/portfolio/fullsize/dr.cut_thebarbershow_blondo2.jpg",
imgUrl2:"assets/img/portfolio/thumbnails/dr.cut_thebarbershow_blondo2.jpg",
},
]
const serviceLinks = [
{
title:'study our themes',
text:'Our themes are updated regularly to keep them bug free!',
icons:"assets/img/logo/Hnet.com-image.svg",
},
{
title:'Haircut',
text:'All dependencies are kept current to keep things fresh.',
icons:"assets/img/logo/clipper.svg",
},
{
title:'Barberos',
text:'You can use this design as is, or you can make changes!',
icons:"assets/img/logo/barber_chair.svg",
},
{
title:'Color',
text:'Is it really open source if its not made with love?',
icons:"assets/img/logo/hairstyle.svg",
},
]
export { galleryLinks, serviceLinks};
index.js
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.scss'
import Header from './src/components/Header'
import Services from './src/components/Services'
export default function Home() {
return (
<div className="container-fluid">
<Head>
<title>Dr Cut TheBarber Show</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="main">
<Header />
<Services />
</main>
<footer className="footer text-center">
<a
className="text-decoration-none text-dark"
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
</div>
)
}
It has nothing to do with the way you are importing Data.js
Here is the source of the error:
const icons = [FaShoppingCart, FaLaptop, FaLock];
{data.map((service, idx) => {
const Icon = icons[idx];
You basically have an array of 3 icons but your serviceLinks array length is 4 in your Data.js so at some point in the map you are doing icons[3] which returns undefined and causes the error.
Add an icon to your icons array to match your last serviceLink.
Working CodeSandbox.

Cannot read property 'map' of undefined in react -js

this is the hole component
import React ,{useState} from 'react';
import useSWR from 'swr'
import Axios from "axios"
import Nav from '../home/nav';
import './mission.css';
import '../home/Cards.css';
import CardItem from '../home/CardItem';
import SweetAlert from 'sweetalert2-react';
const PostuleMission=(props)=>{
const [show,setShow]=useState(false);
const [donnee,setDonnee]=useState({ missions: [] });
const [acceper,setEstaccepe]=useState(0);
const handelAccept =(mission)=>{
//alert("http://localhost:8080/BricoAccept/"+props.user.id+"/"+mission+"/1")
Axios.put("http://localhost:8080/BricoAccept/"+props.user.id+"/"+mission+"/1")
.then(res=>{
setShow(true)
})
.catch(err =>{
alert(err)
})
}
const fetcher = (url) => fetch(url).then(res =>{return res.json()} )
const { data, error } = useSWR('http://localhost:8080/bricoleurs/'+props.user.id, fetcher)
if (error) return (
<div className="d-flex flex-column">
<img alt="..." src="/assets/logo.png" style={{height:"100px",width:"100px"}} className="logo" />
<p className="text-danger">failed to load</p>
</div>);
if (!data) {return (
<div>
<img alt="..." src="/assets/logo.png" className="logo" />
<div className="d-flex flex-row" style={{position:"absolute",left:"50%",right:"50%",top:"45%" }}>
<div className="spinner-grow text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-secondary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-success" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-danger" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-warning" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-info" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-light" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-dark" role="status">
<span className="visually-hidden">Loading...</span>
</div>
</div>
</div>);}
//les cartes
setDonnee(data.missions)
//const Missionss = (data.missions)?((data.missions[0].accepterBrico)?data.missions: []):[];
const Missions= data.missions.map((item)=>{
console.log("hello"+ item.id);
// setEstaccepe(0)
/* Axios.get("http://localhost:8080/accepterbrico/"+props.user.id+"/"+item.id)
.then(res=>{
*/
// alert(item.accepterBrico[0].bricoId)
/*
if(item.accepterBrico) {
for( let i=0;i < item.accepterBrico.length;i++){
if(item.accepterBrico[i].bricoId==props.user.id && item.accepterBrico[i].missionId ==item.id){
if(item.accepterBrico[i].clientAccept==1 && item.accepterBrico[i].bricoAccept==1 ){
setEstaccepe(1) ;
}
else if( item.accepterBrico[i].clientAccept==1 && item.accepterBrico[i].bricoAccept==0 ){
setEstaccepe(2) ;
}
else{
setEstaccepe(0) ;
}
}
}}
*/
const id=item.id;
return(
<div className='cards'>
<div className='cards__container'>
<CardItem
key={item.id}
src={item.images}
text={item.mission_description}
label={item.titre_mission}
path='/comment'
/>
{(acceper==2)? <div className="d-flex flex-row align-items-around p-3">
<button onClick={()=>handelAccept(item.id)} className="btn btn-outline-success">Accepter</button>
<button className="btn btn-outline-danger">Refuser</button>
</div>:((acceper==1)?<div style={{color:"green",fontSize:"2em"}} ><p>Vous l'avais accepté</p></div>:<div style={{color:"red",fontSize:"2em"}} >Pas de réponse</div>)}
</div>
</div>
)
/* })
.catch(err =>{
alert(" inside "+err)
})*/
}
);
return(
<div >
<div id="postulemission"></div>
<Nav data={props.user} />
<div id="postulebox">
<h1>MinuteBlog</h1>
<SweetAlert
show={show}
title="Success"
icon='warning'
text="Congratulations vous avez bien obtenu la mission"
onConfirm={() => {
setShow(false)
}}
/>
{Missions}
</div>
</div>
);
}
export default PostuleMission;
i have a problem in my react code
when i use a loop function( so i can get the data from a list of object that i gave to the map) the map method doesn't read the data that i send to it anymore
this's the map :
enter code
const Missions = data.missions.map((item) => {
if (item.accepterBrico.length > 0) {
for (let i=0; i < item.accepterBrico.length; i++) {
if (item.accepterBrico[i].bricoId == props.user.id && item.accepterBrico[i].missionId == item.id) {
if (item.accepterBrico[i].clientAccept == 1 && item.accepterBrico[i].bricoAccept == 1) {
dosomething;
}
}
}
}
return (<div>..... </div>)
});
here is what the data sent to the map :
{
"id": 591,
"descriptionProfil": null,
"adresse": "harchi",
"phone": "",
"missions": [
{
"id": 586,
"titre_mission": "client#gmail.com",
"state": "Urgent",
"
"bricoleur_choisi": 0,
"idmission": 0,
"accepterBrico": [{
"id": 603,
"bricoId": 591,
"missionId": 597,
"clientAccept": 0,
"bricoAccept": 0
}]
},
details detailsdetailsdetailsdetailsdetailsdetailsdetailsdetails
Issue
All the error is saying is that on at least one of your component renders is that data.missions is not defined. I suspect it is on the initial render because you've not defined accurate enough initial state.
Solution(s)
You can define better initial state that matches what you are attempting to render on the initial render cycle. { missions: [] } as initial data state value would be sufficient in ensuring data.missions is defined and mappable on the initial render cycle.
const [data, setData] = useState({ missions: [] });
You can use a guard clause or Optional Chaining (otherwise known as null-checks) to guard against accessing into potentially null or undefined objects.
const Missions = data.missions && data.missions.map((item) => { .... });
or
const Missions = data.missions?.map((item) => { .... });
or provide a fallback value
const Missions = (data.missions || []).map((item) => { .... });

Having trouble rendering an array of images from an api (Django Rest Framework) response in React

Hi this is my first project in both React and Django Rest Framework and I need to figure this out to complete the project.
The issue I'm having (I believe it's a React one) is that my api is returning an json response which React receives using axios which works fine since when I do the console log all the data is there and Im also able to pass the data to a tag, etc. I would like to display the photos that are being sent to by the api. The link is not the problem as I am able to view the photo in the browser using the link provided by the api. The problem is that I have multiple images in the api response that are set up as an array.
As shown here:
postmanResponse
Response using console:
enter image description here
I guess essentially what I'm asking is there a way that I can make an array/object with the image array that my api is delivering so that I can then use it to show the picture in React?
Any help will be helpful. Thank you!
Here is my code for the React side:
// Import Files
import React, { Component } from 'react';
// Import Axios
import axios from "axios";
// Import Is Mobile
import { isMobile } from 'react-device-detect';
// Import Css
import "./projectDetail.css";
// Mobile Css
import "./projectDetailM.css"
// Lightbox
import { SRLWrapper } from "simple-react-lightbox";
// Import Footer
import Footer from "../Footer/footer"
// Project Detail Class
class ProjectDetail extends Component {
// States
state = {
data: [],
photoIndex: 0,
isOpen: false,
}
// Mount Data to the State
componentDidMount() {
this.handleFetchItem();
}
// Get the project via axios
handleFetchItem = () => {
// Variables
const {
match: { params }
} = this.props
// Set State
this.setState({ loading: true });
// Axios Setup
axios.get('http://127.0.0.1:8000/projects/' + params.ID)
.then(res => {
this.setState({ data: res.data, loading: false });
})
.catch(console.error());
}
// Render the page
render() {
// Const
const { data } = this.state;
const project = data;
// Print to console (Debugging)
//console.log(data);
// Return Page
return (
<div className="projectDetailMainContainer">
<div className="projectDetailGrid">
<div className="projectDetailArea">
<div className="projectNameArea">
<h1 className="projectNameStyling">
{project.title}
</h1>
</div>
<div className="projectAddress1Area">
<h2 className="projectAddress1Styling">
{project.address},
</h2>
</div>
<div className="projectAddress2Area">
<h2 className="projectAddress2Styling">
{project.address2}
</h2>
</div>
<div className="projectCityArea">
<h2 className="projectCityStyling">
{project.city} {project.zipcode}
</h2>
</div>
<div className="projectProgressArea">
<h3 className="projectProgressStyling">
{project.completed}
</h3>
</div>
<div className="projectReturnButton">
<button
className="btnStyleDetailPage"
type="button"
onClick={() => { this.props.history.replace('/projects') }}>
Return to Project List
</button>
</div>
</div>
<div className="projectDetailImageArea">
<SRLWrapper>
<img className="projectImageStyling"
src={require("./placeholders/city.jpg")} alt={project.title} />
</SRLWrapper>
</div>
</div>
<Footer />
</div>
);
}
}
// Export Compoenent
export default ProjectDetail;
You can solve this by implementing a image carousel or iterating over the images array.
First of all you must guarantee that the pictures are properly set on a state (does not matter what type of component). Then, here is one way to show all of the images and solve the problem:
function ImageList(props) {
return (
props.images.map((pic, index) => {
return (
<img key={index} src={pic.src} alt="image" />
);
})
);
}
use map like this
{ data.map(project => { <div className="projectDetailMainContainer">
<div className="projectDetailGrid">
<div className="projectDetailArea">
<div className="projectNameArea">
<h1 className="projectNameStyling">
{project.title}
</h1>
</div>
<div className="projectAddress1Area">
<h2 className="projectAddress1Styling">
{project.address},
</h2>
</div>
<div className="projectAddress2Area">
<h2 className="projectAddress2Styling">
{project.address2}
</h2>
</div>
<div className="projectCityArea">
<h2 className="projectCityStyling">
{project.city} {project.zipcode}
</h2>
</div>
<div className="projectProgressArea">
<h3 className="projectProgressStyling">
{project.completed}
</h3>
</div>
<div className="projectReturnButton">
<button
className="btnStyleDetailPage"
type="button"
onClick={() => { this.props.history.replace('/projects') }}>
Return to Project List
</button>
</div>
</div>
<div className="projectDetailImageArea">
<SRLWrapper>
<img className="projectImageStyling"
src={require("./placeholders/city.jpg")}
alt={project.title} />
</SRLWrapper>
</div>
</div>
<Footer />
</div>
})}
for the images you can access them by index like this
{project.images[0].src}
{project.images[1].src}
{project.images[2].src}
example:
<img src={project.images[0].src} alt="image" />

A modal inside a Map Function In ReactJs has error message

I would like to ask question about some kind of grid gallery for a portfolio section. Each grid has a overlay which could be triggered by mouseover and the grids are generated by a map function and data in the grids are linked with a json file. The problem is that when I put a draft modal that I supposed it is for the grid , an error message showed "TypeError: Cannot read property 'toggleModal' of undefined" for this tag . Thanks for any solution.
import React, { Component } from 'react';
import Modal from './Modal';
class Portfolio extends Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
}
toggleModal = () => {
this.setState({
isOpen: !this.state.isOpen
});
}
render() {
if(this.props.data){
var projects = this.props.data.projects.map(function(projects){
var projectImage = 'images/portfolio/'+projects.image;
return <div key={projects.title} className="columns portfolio-item">
<div className="item-wrap">
<a href={projects.url} className="open-popup" title={projects.title}>
<img alt={projects.title} src={projectImage} />
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{projects.title}</h5>
<p>{projects.category}</p>
</div>
</div>
<div className="link-icon"><i className="fa fa-link"></i></div>
</a>
</div>
<button onClick={this.toggleModal}>
Open the modal
</button>
<Modal show={this.state.isOpen} onClose={this.toggleModal} >
Here's some content for the modal
</Modal>
</div>
})
}
return (
<section id="portfolio">
<div className="row">
<div className="twelve columns collapsed">
<h1>Check Out Some of My Works.</h1>
<div id="portfolio-wrapper" className="bgrid-quarters s-bgrid-thirds cf">
{projects}
</div>
</div>
</div>
</section>
);
}
}
export default Portfolio;
and the Modal.js is below:
import React from 'react';
import PropTypes from 'prop-types';
class Modal extends React.Component {
render() {
// Render nothing if the "show" prop is false
if(!this.props.show) {
return null;
}
// The gray background
const backdropStyle = {
position: 'fixed',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0,0,0,0.3)',
padding: 50
};
// The modal "window"
const modalStyle = {
backgroundColor: '#fff',
borderRadius: 5,
maxWidth: 500,
minHeight: 300,
margin: '0 auto',
padding: 30
};
return (
<div className="backdrop" style={backdropStyle}>
<div className="modal" style={modalStyle}>
{this.props.children}
<div className="footer">
<button onClick={this.props.onClose}>
Close
</button>
</div>
</div>
</div>
);
}
}
Modal.propTypes = {
onClose: PropTypes.func.isRequired,
show: PropTypes.bool,
children: PropTypes.node
};
export default Modal;
The error is caused from this line:
var projects = this.props.data.projects.map(function(projects){
Since you used this.toggleModal inside this function, the this context is linking to this function, not the React component.
The solution is to use an arrow function like this:
var projects = this.props.data.projects.map((projects) => {
On a side note, it's not a good idea to define a variable inside a block and use it outside of it.
This is my revised version, thanks. What should I do if I want to add next and previous function in modal in order to show next or previous project information? Thanks. I am sorry that I am new with React and Javascript.
import React, { Component } from 'react';
import Modal from './Modal';
class Portfolio extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
activeProjects:"",
activeProjectImage:""
};
}
toggleModal = (projects,projectImage) => {
this.setState({activeProjects:projects, activeProjectImage:projectImage},() =>
this.setState({
isOpen: !this.state.isOpen
}));
}
render() {
if(this.props.data){
var projects = this.props.data.projects.map((projects) => {
var projectImage = 'images/portfolio/'+projects.image;
return <div key={projects.title} className="columns portfolio-item">
<div className="item-wrap">
<a onClick={() => this.toggleModal(projects,projectImage)} className="open-popup" title={projects.title}>
<img alt={projects.title} src={projectImage} />
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{projects.title}</h5>
<p>{projects.category}</p>
</div>
</div>
<div className="link-icon"><i className="fa fa-link"></i></div>
</a>
</div>
</div>
})
}
return (
<section id="portfolio">
<div className="row">
<div className="twelve columns collapsed">
<h1>Check Out Some of My Works.</h1>
<div id="portfolio-wrapper" className="bgrid-quarters s-bgrid-thirds cf">
{projects}
<Modal show={this.state.isOpen} onClose={this.toggleModal} >
<img alt={this.state.activeProjects.title} src={this.state.activeProjectImage} />
</Modal>
</div>
</div>
</div>
</section>
);
}
}
export default Portfolio;

Categories

Resources