简体   繁体   English

如何在 React 中的兄弟组件之间传递数据?

[英]How can I pass data between sibling components in React?

I am working on a React eCommerce website and I am having difficulties in showing the pdp (product detail page).我在一个 React 电子商务网站上工作,我在显示 pdp(产品详细信息页面)时遇到了困难。 The process should be that whenever a user clicks on a <Picture Card /> component, then it should open up the pdp of that product.该过程应该是,每当用户单击<Picture Card />组件时,它应该打开该产品的 pdp。 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).现在,如果发生这种情况,我设法注销了每个产品的名称和 ID,但我无法让它出现在 pdp 页面上(我不知道如何在这里传递数据)。

I cannot understand why setState() is not working correctly.我不明白为什么 setState() 不能正常工作。

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 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图片卡.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

you can't pass data through siblings, you need to lift up state or use other strategies.不能通过兄弟姐妹传递数据,您需要提升 state或使用其他策略。 you need to find a common 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 .您需要找到一个共同的祖先(在您的情况下为 App.js)来放置您的 state,并将您的 state 和 setState Pdp作为道具传递给Shop this is the simplest approach.这是最简单的方法。

with a deep nested tree you would need to pass down to each component 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.在这种情况下,您可以使用上下文 API 来创建提供程序并直接使用。

for more complex 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 components. for more complex 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 components.

about setState:关于 setState:

setState is async, to print an updated state you can console.log on componentDidUpdate life cycle . setState 是异步的,要打印更新的 state 您可以 console.log on componentDidUpdate 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还可以接受第二个参数,一个回调 function,它将在您的状态更新后运行,因此您可以控制台记录您更新的 state。

setState is an async function, so that's why the console.log is not printing the correct productId. setState 是一个异步 function,这就是为什么 console.log 没有打印正确的 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 componentWillReceiveProps如果您想查看更改,请将其添加到componentWillReceiveProps

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

setState method is an asynchronous method that's batched. setState 方法是批处理的异步方法。 This means that multiple setState calls are batched before a component is rerendered with the new state.这意味着在使用新的 state 重新呈现组件之前,会批处理多个setState调用。 setState doesn't immediately mutate the state but creates a pending state transaction. setState不会立即改变 state 而是创建待处理的 state 事务。 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);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM