最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I pass data between sibling components in React? - Stack Overflow

programmeradmin1浏览0评论

I am working on a React eCommerce website and I am having difficulties in showing the pdp (product detail page). The process should be that whenever a user clicks on a <Picture Card /> ponent, then it should open up the pdp of that product. Right now, if this happens I managed to log out the name and id of each product, but I cannot make it appear on the pdp page (I dont know how to pass the data here).

I cannot understand why setState() is not working correctly.

What am I missing ? Thanks in advance!

App.js
   ├── Header.js
   ├── Home.js
   ├── shop.js
            ├── PictureCard.js
   ├── Pdp.js
   ├── About.js
   └── Footer.js

My code:

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.state = {
               productId: 1,
               productTitle: "",
               productPrice: "",
               productDescription: "",
               productImage: ""
          }
          this.handleClick = this.handleClick.bind(this)
     }

     handleClick(id, name, price, description, image) {
          console.log(id) //the id here is correct
          this.setState((prevState) => {
               return {
                   productId: prevState.productId + 1  
               }
          })
          console.log(this.state.productId)  //productId doen not update
     }
     
     //console.log(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}
                       />
                       <PictureCard
                            id="3"
                            image={profile2}
                            title="Mullaghmore Runner"
                            price="20"
                            description="Being active during lockdown in County Sligo"
                            handleClick={this.handleClick}
                       />
                   </div>
               </div>
           )
     }
}

export default Shop;

PictureCard.js

import React from "react"

import "./PictureCard.css"

import { Link } from "react-router-dom"

class PictureCard extends React.Component {
    constructor() {
        super()
    }

    render() {
        return(
            <div className="picure-card-container" onClick={() => 
                this.props.handleClick(this.props.id, this.props.title, this.props.price, this.props.description, this.props.image)}>
                <Link to = {`/pdp/${this.props.title}`} className="no-dec">
                    <img src={this.props.image} className="picture-card-image"></img>
                    <h6 className="picture-card-title">{this.props.title}</h6>
                    <p className="picture-card-price">€ {this.props.price}</p>
                </Link>
            </div>
        )
    }
}

export default PictureCard

I am working on a React eCommerce website and I am having difficulties in showing the pdp (product detail page). The process should be that whenever a user clicks on a <Picture Card /> ponent, then it should open up the pdp of that product. Right now, if this happens I managed to log out the name and id of each product, but I cannot make it appear on the pdp page (I dont know how to pass the data here).

I cannot understand why setState() is not working correctly.

What am I missing ? Thanks in advance!

App.js
   ├── Header.js
   ├── Home.js
   ├── shop.js
            ├── PictureCard.js
   ├── Pdp.js
   ├── About.js
   └── Footer.js

My code:

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.state = {
               productId: 1,
               productTitle: "",
               productPrice: "",
               productDescription: "",
               productImage: ""
          }
          this.handleClick = this.handleClick.bind(this)
     }

     handleClick(id, name, price, description, image) {
          console.log(id) //the id here is correct
          this.setState((prevState) => {
               return {
                   productId: prevState.productId + 1  
               }
          })
          console.log(this.state.productId)  //productId doen not update
     }
     
     //console.log(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}
                       />
                       <PictureCard
                            id="3"
                            image={profile2}
                            title="Mullaghmore Runner"
                            price="20"
                            description="Being active during lockdown in County Sligo"
                            handleClick={this.handleClick}
                       />
                   </div>
               </div>
           )
     }
}

export default Shop;

PictureCard.js

import React from "react"

import "./PictureCard.css"

import { Link } from "react-router-dom"

class PictureCard extends React.Component {
    constructor() {
        super()
    }

    render() {
        return(
            <div className="picure-card-container" onClick={() => 
                this.props.handleClick(this.props.id, this.props.title, this.props.price, this.props.description, this.props.image)}>
                <Link to = {`/pdp/${this.props.title}`} className="no-dec">
                    <img src={this.props.image} className="picture-card-image"></img>
                    <h6 className="picture-card-title">{this.props.title}</h6>
                    <p className="picture-card-price">€ {this.props.price}</p>
                </Link>
            </div>
        )
    }
}

export default PictureCard
Share Improve this question edited Dec 29, 2020 at 14:15 zawrdo asked Dec 29, 2020 at 14:08 zawrdozawrdo 511 silver badge10 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

you can't pass data through siblings, you need to lift up state or use other strategies. you need to find a mon ancestor (in your case App.js) to place your state, and pass down your state and your setState function as props to Shop and Pdp. this is the simplest approach.

with a deep nested tree you would need to pass down to each ponent until it finds the final consumer. in this case instead you could use the Context API where you create a provider and you can consume directly.

for more plex state management (a shopping cart would fit the case) you have options like redux where you have a redux state, with reducers that handle state properly, and connect with ponents.

about setState:

setState is async, to print an updated state you can console.log on ponentDidUpdate life cycle. also setState can take a second argument, a callback function that will run after your state's update so you can console.log your updated state.

setState is an async function, so that's why the console.log is not printing the correct productId.

handleClick(id, name, price, description, image) {
          console.log(id) //the id here is correct
          this.setState((prevState) => {
               return {
                   productId: prevState.productId + 1  
               }
          })
          console.log(this.state.productId)  //setState hasn't happened
     }

if you want to see the changes, add it to ponentWillReceiveProps

ponentWillReceiveProps(nextProps) {
     console.log(nextProps.productId);
}

setState method is an asynchronous method that's batched. This means that multiple setState calls are batched before a ponent is rerendered with the new state. setState doesn't immediately mutate the state but creates a pending state transaction. Do this if you want to see the result of the console:

this.setState((prevState) => {
               return {
                    ...prevState,
                    productId: prevState.productId + 1  
               },() => {
    console.log(this.state.productId);
});
发布评论

评论列表(0)

  1. 暂无评论