![](/img/trans.png)
[英]How to render and update child elements coming from a parent component in React?
[英]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.