![](/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.