【问题标题】:React pass data from mapped child to new componentReact 将数据从映射的子组件传递到新组件
【发布时间】:2019-08-16 09:25:31
【问题描述】:

我有一个购物目录,我想从孩子那里获取数据并传递给一个新组件。我已经从 JSON 映射数据(后来是一个 api 调用),我想从映射的子组件中获取一些道具,即名称、价格和计数(这是组件的一部分,而不是原始数据)

数据(名称/价格)-> 主组件-> 映射到子组件(有计数)-> 主组件

我应该使用表格吗?一些生命周期方法?还原?路由器?不太清楚该怎么做。

数据

const marketData = [
    {
        id: 1,
        name: "product1",
        price: "$2",
    },
    {
        id: 2,
        name: "product2",
        price: "$3",
    },
    {
        id: 2,
        name: "product3",
        price: "$3",
    }
]

父母

import React, { Component } from 'react';
import MarketItem from './MarketItem.js'
import MarketData from './MarketData.js'


class MarketContainer extends Component {
  constructor() {
    super()
    this.state = {
      market: MarketData
    }
  }

  render() {
    const marketItems = this.state.market.map(item => <MarketItem key={item.id} product={item} />)

    return (
      <div>
          {marketItems}
      </div>
    );
  }
}

export default MarketContainer;

孩子

import React, {Component}  from 'react';

class MarketItem extends Component {
constructor(props){
  super(props)
  this.state = {
        count : 0
      }
}


IncrementItem = () => {
  this.setState({ count: this.state.count + 1 });
}
IncrementItemBy10 = () => {
  this.setState({ count: this.state.count + 10 });
}

render(){
    return (
      <div className="MarketItem">
        <div className="market__content">
            <h1>{this.props.product.name + " " + this.props.product.price}</h1>   
        </div> 
            <div className="market__counter">
              <button className="market__button--minus" onClick={this.DecreaseItem}>-</button>
              <p>{this.state.count}</p>
              <button className="market__button--plus" onClick={this.IncrementItem}>+</button>
            </div>

      </div>
    );
  }
}
export default MarketItem;

在父级 (marketContainer) 中,我想从每个子组件中获取数量、名称和价格,然后创建一个新组件。我已经尝试过表单,但对我是否应该使用生命周期方法并不满意?还原?路由器?

【问题讨论】:

  • 也许您应该使用回调属性渲染 &lt;MarketItem&gt; 组件以通知 &lt;MarketContainer&gt; 计数已更改?
  • 你可以通过使用 react refs 来做到这一点。但这不是最好的方法,所以我建议你使用 redux,使用 redux 你可以获取任何组件的数据。
  • 据我了解,您需要 MarketContainer 中的“计数”吗?
  • 另外一个选项是您可以在父组件中设置状态并将回调传递给子组件,当计数更改时调用此回调并更新父组件中的状态。

标签: reactjs


【解决方案1】:

我认为这是您应该设计状态以保持计数与产品相关的方式。

import React, { Component } from 'react';
import MarketItem from './MarketItem.js'

class MarketContainer extends Component {
 constructor() {
    super()
    this.state = {
          market:  [
            {
                id: 1,
                name: "product1",
                price: "$2",
                count:0,
            },
            {
                id: 2,
                name: "product2",
                price: "$3",
                count:0,
            },
            {
                id: 2,
                name: "product3",
                price: "$3",
                count:0,
            }
        ]
    }
}

IncrementItem = (i) => {
    let market = this.state.market;
    market[i].count += 1; 
    this.setState({market});
}

DecreaseItem = (i) => {
    let market = this.state.market;
    market[i].count -= (market[i].count > 0) ? 1: 0; 
    this.setState({market});
}

render() {
    const marketItems = this.state.market.map(item => <MarketItem key={item.id} product={item}  i={i} IncrementItem={this.IncrementItem} DecreaseItem={this.DecreaseItem}/>)

    return (
      <div>
          {marketItems}
      </div>
    );
 }
}

export default MarketContainer;

孩子

import React, {Component}  from 'react';

class MarketItem extends Component {
 constructor(props){
   super(props);
 }

 render(){
    return (
      <div className="MarketItem">
        <div className="market__content">
            <h1>{this.props.product.name + " " + this.props.product.price}</h1>   
        </div> 
            <div className="market__counter">
              <button className="market__button--minus" onClick={() => this.props.DecreaseItem(this.props.i)}>-</button>
              <p>{this.state.count}</p>

              <button className="market__button--plus" onClick={() => this.props.IncrementItem(this.props.i)}>+</button>
            </div>

      </div>
    );
 }
}

export default MarketItem;

【讨论】:

    【解决方案2】:

    您可以在 MarketContainer 中为需要传递给其他子组件的计数和其他字段定义状态。

    我试图包含代码来说明我将如何做到这一点。

       //MarketData.js
        //after ajax request
        const marketData = [
    
          {
            id: 1, 
            name: "product1", 
            price: "$1"
          }, 
    
          {
            id: 2, 
            name: "product2", 
            price: "$2"
          }
        ]; 
    
        //We can format market data as per we need it in components
    
        const formattedMarketData = marketData.map(e => {
            e.count = 0; 
            return e;
        });
    
    
    
    
    
      //parent component
        //let us define all the things which we might need to pass to other components in here
        // ... 
    
        constructor()
        {
            super(); 
            this.state = {
                markets: formattedMarketData
            }
    
        }
    
        /* we are handling all state changes in parent component
         we have updated state in parent component
         we can deliver the changed state to any other components */
        IncrementItem = (id) => {
            this.setState((prevState) => {
                const markets = {...prevState.markets}; 
                const index = markets.findIndex(x => x.id ===id);
                markets[index].count = prevState.markets[index].count + 1; 
                return {
                    markets: markets
                };
            });
        }
    
        DecrementItem = (id) => {
            this.setState((prevState) => {
                const markets = {...prevState.markets};
                const index = markets.findIndex(x => x.id ===id);
                markets[index].count = prevState.markets[index].count - 1; 
                return {
                    markets: markets
                };
            });
        }
    
        render() {
            const marketItems = this.state.market.map(item => <MarketItem IncrementItem={this.IncrementItem} DecrementItem={this.DecrementItem} key={item.id} product={item} />)
    
            return (
              <div>
                  {marketItems}
              </div>
            );
          }
    
    
    
    //child component 
    
    export default (props) => {
     const {IncrementItem, DecreaseItem, product} = props;
     <div className="MarketItem">
            <div className="market__content">
                <h1>{product.name + " " + product.price}</h1>   
            </div> 
                <div className="market__counter">
                  <button className="market__button--minus" onClick={() => {DecreaseItem(product.id)}}>-</button>
                  <p>{product.count}</p>
                  <button className="market__button--plus" onClick={() => {IncrementItem(product.id)}}>+</button>
                </div>
    
          </div>
    };
    

    【讨论】:

      【解决方案3】:

      你需要在 React 中使用 Lifting State Up

      【讨论】:

        【解决方案4】:
        class MarketContainer extends Component {
           state = {
            count : 0
           }
        
           IncrementItem = () => {
           this.setState({count: count + 1})
           }
        
           DecreaseItem = () => {
           this.setState({count: count - 1})
           }
        
         render() {
        const marketItems = this.state.market.map(item => <MarketItem key={item.id} 
          product={item} IncrementItem={this.IncrementItem} DecreaseItem={DecreaseItem} count={this.state.count}/>)
        
           return (
            <div>
              {marketItems}
            </div>
          );
         }
        }
        

        现在,当用户单击增量和减量图标时,您可以在 MarketItem 组件上使用 IncrementItemDecreaseItem 道具。我们还从父组件传递 count 的值,以便您可以在子组件中显示。

        【讨论】:

          猜你喜欢
          • 2019-08-14
          • 2022-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-26
          • 1970-01-01
          • 1970-01-01
          • 2020-09-23
          相关资源
          最近更新 更多