Reputation: 51
I am working on a React eCommerce website and I am having difficulties in showing the pdp complete with all the fields I need. The process should be that whenever a user clicks on a <Picture Card />
component, then it should open up the pdp of that product. Right now I get an error:
src\components\Main.js
Line 14:128: 'productData' is not defined no-undef
I simply want to pass the state of my <App />
component to my <Pdp />
component and to do this I have to pass trough my <Main />
component where routes is happening and creating me problems.
What am I missing ? Thanks in advance!
My code structure:
App.js
├── Header.js
├── Home.js
├── shop.js
├── PictureCard.js
├── Pdp.js
├── About.js
└── Footer.js
My code:
App.js
import React from "react"
import Header from "./components/Header"
import Main from "./components/Main"
import Footer from "./components/Footer"
import './App.css';
class App extends React.Component {
constructor() {
super()
this.state = {
productId: "",
productTitle: "",
productPrice: "",
productDescription: "",
productImage: ""
}
}
handleCallback = (id, name, price, description, image) => {
alert(id)
this.setState({
productId: id,
productTitle: name,
productPrice: price,
productDescription: description,
productImage: image
})
}
render() {
return (
<div className="App">
<Header />
<Main
parentCallback = {this.handleCallback}
productData = {this.state.productPrice}
/>
<Footer />
</div>
)
}
}
export default App
Main.js
import React from 'react'
import { Switch, Route } from 'react-router-dom'
import Home from './Home'
import Shop from './Shop'
import About from './About'
import Pdp from './Pdp'
function Main({parentCallback}) {
return (
<Switch> {/* The Switch decides which component to show based on the current URL.*/}
<Route exact path='/' render = {(props) => (<Home parentCallback={parentCallback} {...props}/>)}/>
<Route exact path='/shop' render = {(props) => (<Shop parentCallback={parentCallback} {...props}/>)}/>
<Route exact path='/pdp/:productTitle' render = {(props) => (<Pdp parentCallback={parentCallback} productData={productData} {...props}/>)}/>{/*problem here! why?*/}
<Route exact path='/about' render = {(props) => (<About parentCallback={parentCallback} {...props}/>)}/>
</Switch>
)
}
export default Main
Shop.js
import React from "react"
import PictureCard from "./PictureCard"
import profile2 from "../images/profile2.jpg"
import { Link } from "react-router-dom"
import './Shop.css'
class Shop extends React.Component {
constructor() {
super()
this.handleClick = this.handleClick.bind(this)
}
handleClick(id, name, price, description, image) {
console.log(id, name, price, description, image)
this.props.parentCallback(id, name, price, description, image)
}
render() {
return (
<div className="shop-container">
<h3 className="filter-title"><Link to="/shop" className="no-dec">All pictures</Link></h3>
<div className="shop-grid">
<PictureCard
id="1"
image={profile2}
title="Strandhill Cannon Susnet"
price="20"
description="Colourful sunset at the cannon of Strandhill during lockdown"
handleClick={this.handleClick}
/>
<PictureCard
id="2"
image={profile2}
title="Bundoran in Winter"
price="20"
description="Snowy mountains view behind Bundoran colourful houses"
handleClick={this.handleClick}
/>
</div>
</div>
)
}
}
export default Shop;
Pdp.js
import React from "react"
import profile2 from "../images/profile2.jpg"
import { Link } from "react-router-dom"
import './Pdp.css'
class Pdp extends React.Component {
constructor(props) {
super(props)
this.state = {
price: this.props.productData
}
}
render() {
return (
<div className="pdp-page">
<h3 className="filter-title">
<Link to="/shop" className="no-dec">All pictures</Link> <span>›</span> <a href="" className="no-dec">{this.props.match.params.productTitle}</a>
</h3>
<div className="pdp-container">
<div>
<img src={this.props.image} className="pdp-image"></img>
</div>
<div className="pdp-info-container">
<h3 className="pdp-title">{this.props.match.params.productTitle}</h3>
<p className="pdp-info-paragraph">€ {this.state.price}</p>
<p className="pdp-info-paragraph">{this.props.description}</p>
<button className="purchase-button">Purchase</button>
</div>
</div>
</div>
)
}
}
export default Pdp;
Upvotes: 0
Views: 138
Reputation: 10382
as the docs points out, your render will be called with route props. given that, the props params (route props) at your function will be passed to your component, not your outside declared props. you need to provide your extra props aside to your component have access to it:
import React from 'react'
import { Switch, Route } from 'react-router-dom'
import Home from './Home'
import Shop from './Shop'
import About from './About'
import Pdp from './Pdp'
function Main(props) {
return (
<Switch> {/* The Switch decides which component to show based on the current URL.*/}
<Route exact path='/' render = {(routeProps) => (<Home {...props} {...routeProps} />)}/>
<Route exact path='/shop' render = {(routeProps) => (<Shop {...props} {...routeProps} />)}/>
<Route exact path='/pdp/:productTitle' render = {(routeProps) => (<Pdp {...props} {...routeProps} />)}/>
<Route exact path='/about' render = {(routeProps) => (<About {...props} {...routeProps} />)}/>
</Switch>
)
}
export default Main
fwiw since the props you're passing has the same name as the prop at your component you don't need to destructure it, you could only spread your props directly
Upvotes: 0
Reputation: 6582
you need to define the props and the destructure it if you're using it directly:
function Main(props) {
const {parentCallback} = props;
return (
<Switch> {/* The Switch decides which component to show based on the current URL.*/}
<Route exact path='/' render = {(props) => (<Home parentCallback={parentCallback} {...props}/>)}/>
<Route exact path='/shop' render = {(props) => (<Shop parentCallback={parentCallback} {...props}/>)}/>
<Route exact path='/pdp/:productTitle' render = {(props) => (<Pdp parentCallback={parentCallback} productData={productData} {...props}/>)}/>{/*problem here! why?*/}
<Route exact path='/about' render = {(props) => (<About parentCallback={parentCallback} {...props}/>)}/>
</Switch>
)
}
Upvotes: 1