簡體   English   中英

反應:如何從子組件渲染父組件?

[英]React: How to render a parent component from child component?

我的任務是為一個客戶構建一個項目,該項目需要一個父組件包裝三個子組件。 具體來說,父組件根據以下方式將子組件呈現為:

父母=頂+中+底

父組件代表一組項目中的一個。

在TOP組件中,有一個菜單按鈕,該菜單按鈕顯示該組中所有項目的列表,其目的是用戶單擊這些鏈接之一,所選項目將顯示(PARENT將“重新渲染”到新項目-PARENT中存在一種邏輯,該邏輯將導致所選擇的第二項而不是第一項出現。

我在這里講的很松散,如果不清楚,我可以提供代碼(我認為應該這樣)。

我遇到的主要問題是嘗試從子組件之一“重新渲染”父組件。 本質上,有一個菜單按鈕出現,顯示相關項目的列表。 單擊這些項目之一應重新呈現父組件,但這次顯示所選項目。 我不知道如何做到這一點,並希望得到一些建議或幫助。 我花了整個上午研究這個主題,並嘗試了一些建議的方法,但沒有成功。

到目前為止,也許我采取的方法並不是完成此類任務的最佳方法。 無論如何,任何幫助都是非常有幫助的。 謝謝!


編輯:現在工作

編輯#2:由於已經獲得了很多意見,我只是想澄清一下,這是一個概念證明,並且也是非常簡化的原型/早期版本(沒有花哨的翻譯等)-這個想法可以起作用。 ,因為我們當時不確定。 自從我從事類似工作以來已經有一段時間了,但是我真的很感謝我為這樣一個令人困惑的問題所提供的所有幫助,以及當時那是一件非常有趣且具有挑戰性的任務。

 import React from 'react';

import CardHeader from 'components/CardHeader';
import CardContent from 'components/CardContent';
import CardFooter from 'components/CardFooter';

module.exports = React.createClass({

  getInitialState: function () {
    return {
      fullData: '',

      //Core Card
      userId: '',
      cardStack: '',
      cardId: '',

      //Load Card
      loadCard: '1',

      //Optional Fields
      name: '',
      type: '',
      headline: '',
      subtitle: '',
      ctext: '',
      imageUrl: '',
      price: '',
      mapCoordinates: '',
      logoUrl: '',
      order: '',
      email: '',
      sponsorUrl: '',
      pollId: '',
      socialButton: ''
    };
  }
  ,

  componentWillMount: function () {

    //fetches cardStack and card API JSON
    /** JSON Structure:
     [
     cardStack: ...,
     cards: ...
     ]
     **/

    var fetch = function (userId, cardStackId) {

      //AJAX

      var json = {
        'cardStack': {'id': '1', 'name': 'Test Card Stack', 'userID': 'O1AB0001'},
        'cards': [{
          'id': '1',
          'name': 'Test Card 1',
          'cardStack': '1',
          'meta': 'meta_note',
          'socialButton': 'twitter',
          'sponsorUrl': 'https://iwantmyname.com/images/logo-url-shortener-droplr.png',
          'order': 1,
          'logoUrl': 'https://iwantmyname.com/images/logo-url-shortener-droplr.png',
          'product': {
            'headline': 'Headline Test',
            'subtitle': 'Subtitle Test',
            'ctext': 'Hello!!!!',
            'imageUrl': 'http://the-mpas.com/wp-content/uploads/2012/04/Image-pic-54-copy.jpg',
            'price': '20.00'
          }
        }, {
          'id': '2',
          'name': 'Test Card 2',
          'cardStack': '1',
          'meta': 'meta_note',
          'socialButton': 'twitter',
          'sponsorUrl': 'https://iwantmyname.com/images/logo-url-shortener-droplr.png',
          'order': 2,
          'logoUrl': 'https://iwantmyname.com/images/logo-url-shortener-droplr.png',
          'product': {
            'headline': 'Headline Test 2',
            'subtitle': 'Subtitle Test 2',
            'ctext': 'Hello 2!!!!',
            'imageUrl': 'http://the-mpas.com/wp-content/uploads/2012/04/Image-pic-54-copy.jpg',
            'price': '30.00'
          }
        }]
      };

      return json;
    };

    var that = this;

    var getCard = function (cardArray, cardOrder) {
      var card;
      for (var key in cardArray) {
        if (cardArray[key].order == cardOrder) {
          card = cardArray[key];
        }
      }

      if ('product' in card) {
        that.setState({
          type: 'product',
          headline: card.product.headline,
          subtitle: card.product.subtitle,
          ctext: card.product.ctext,
          imageUrl: card.product.imageUrl,
          price: card.product.price
        })
      }
      if ('article' in card) {
        that.setState({
          type: 'article',
          headline: card.article.headline,
          ctext: card.article.ctext
        })
      }

      if ('map' in card) {
        that.setState({
          type: 'map',
          mapCoordinates: card.map.mapCoordinates
        })
      }

      if ('relatedvideo' in card) {
        that.setState({
          type: 'relatedvideo',
          headline: card.relatedvideo.headline,
          ctext: card.relatedvideo.ctext,
          imageUrl: card.relatedvideo.imageUrl
        })
      }

      if ('poll' in card) {
        that.setState({
          type: 'poll',
          headline: card.poll.headline,
          subtitle: card.poll.subtitle,
          pollId: card.poll.pollId
        })
      }

      if ('imagegallery' in card) {
        that.setState({
          type: 'imagegallery',
          headline: card.imagegallery.headline,
          ctext: card.imagegallery.ctext,
          imageUrl: card.imagegallery.imageUrl
        })
      }

      if ('profile' in card) {
        that.setState({
          type: 'profile',
          headline: card.profile.headline,
          ctext: card.profile.ctext,
          imageUrl: card.profile.imageUrl
        })
      }

      if ('newsletter' in card) {
        that.setState({
          type: 'newsletter',
          email: card.newsletter.email
        })
      }
      return card;
    };

//Entry Point HERE
    var userId = 'O1AB0001', cardStackId = 1;
    var json = fetch(userId, cardStackId);
    var myCard = getCard(json.cards, this.state.loadCard);

//Set core data
    this.setState({

      //fulldata
      fullData: json,

      //card stack
      userId: json.cardStack.name,
      cardStack: json.cardStack.id,

      //card
      cardId: myCard.id,
      socialButton: myCard.socialButton,
      order: myCard.order,
      sponsorUrl: myCard.sponsorUrl,
      logoUrl: myCard.logoUrl,
      meta: myCard.meta,
      name: myCard.name
    });
  },

  setNew: function (nextState) {

    var nsFullData = nextState.fullData;
    var nsCards = nsFullData.cards;
    var nsCardStack = nsFullData.cardStack;

    var that = this;
    var getCard = function (cardArray, cardOrder) {
      var card;
      for (var key in cardArray) {
        if (cardArray[key].order == cardOrder) {
          card = cardArray[key];
        }
      }

      if ('product' in card) {
        that.setState({
          type: 'product',
          headline: card.product.headline,
          subtitle: card.product.subtitle,
          ctext: card.product.ctext,
          imageUrl: card.product.imageUrl,
          price: card.product.price
        })
      }
      if ('article' in card) {
        that.setState({
          type: 'article',
          headline: card.article.headline,
          ctext: card.article.ctext
        })
      }

      if ('map' in card) {
        that.setState({
          type: 'map',
          mapCoordinates: card.map.mapCoordinates
        })
      }

      if ('relatedvideo' in card) {
        that.setState({
          type: 'relatedvideo',
          headline: card.relatedvideo.headline,
          ctext: card.relatedvideo.ctext,
          imageUrl: card.relatedvideo.imageUrl
        })
      }

      if ('poll' in card) {
        that.setState({
          type: 'poll',
          headline: card.poll.headline,
          subtitle: card.poll.subtitle,
          pollId: card.poll.pollId
        })
      }

      if ('imagegallery' in card) {
        that.setState({
          type: 'imagegallery',
          headline: card.imagegallery.headline,
          ctext: card.imagegallery.ctext,
          imageUrl: card.imagegallery.imageUrl
        })
      }

      if ('profile' in card) {
        that.setState({
          type: 'profile',
          headline: card.profile.headline,
          ctext: card.profile.ctext,
          imageUrl: card.profile.imageUrl
        })
      }

      if ('newsletter' in card) {
        that.setState({
          type: 'newsletter',
          email: card.newsletter.email
        })
      }
      return card;
    };

    var myCard = getCard(nsCards, this.state.loadCard);

    this.setState({

      //fulldata
      fullData: nsFullData,

      //card stack
      userId: nsCardStack.name,
      cardStack: nsCardStack.id,

      //card
      cardId: myCard.id,
      socialButton: myCard.socialButton,
      order: myCard.order,
      sponsorUrl: myCard.sponsorUrl,
      logoUrl: myCard.logoUrl,
      meta: myCard.meta,
      name: myCard.name
    });
  },

  componentWillUpdate: function (nextProps, nextState) {
    if (nextState.loadCard !== this.state.loadCard) {
      this.setNew(nextState);
    }
  },

  render: function () {

    return (
      <div className='sg-cardBase'>
        <div className='sg-cardHeaderSection'>
          <CardHeader setLoadCard={i => this.setState({loadCard: i})} data={this.state}/>
        </div>
        <div className='sg-cardContentSection'>
          <CardContent data={this.state}/>
        </div>
        <div className='sg-cardFooterSection'>
          <CardFooter data={this.state}/>
        </div>
      </div>
    );
  }
});

您需要將回調傳遞給子組件,以修改父組件的狀態。 然后,父級可以根據該狀態重新渲染。 例如:

var Parent = React.createClass({
  getInitialState: function() {
    return { index: 1 };
  },
  render: function() {
    return <div>
        <Child setIndex={i => this.setState({index: i})}/>
        <p>{this.state.index}</p>
      </div>
  }
})

var Child = React.createClass({
  render: function() {
    <button onClick={() => this.props.setIndex(5)}/>
  }
});

在您的情況下,當前選定的項目應以父組件的狀態存儲,並且回調應傳遞到頂部組件,以便它可以更改選定的項目。

我假設頂部和底部保持不變,中間根據菜單進行更改。

頂部從父級獲取回調。 在頂部選擇一個選項時,它會調用回調changeCurrentView ,並通知它有關currentView 回調changeCurrentView設置父狀態,調用render方法。

您現在可以在父級中更改渲染中間,但是我建議中間將重新渲染不同的視圖。 因此Middle將從父級獲取currentView作為視圖,然后重新呈現所需的視圖:

 class Parent extends React.Component { constructor(props) { super(props); this.state = { currentView: 0 }; this.changeCurrentView = this.changeCurrentView.bind(this); } changeCurrentView(currentView) { this.setState({ currentView }); } render() { return ( <div> <Top changeView={ changeCurrentView } /> <Middle currentView = { this.state.currentView } /> <Bottom /> </div> ); } } const views = [ <View1 />, <View2 />, <View3 /> ]; const Middle = ({ currentView }) => ( <div>{ views[currentView]; </div> ); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM