React.js - 实现组件的排序 [英] React.js - Implementing sorting of components
问题描述
我正在尝试学习React概念,特别是re:状态和动态UI,通过编写一个小型的运动名单类UI。我已经包含下面的代码,整个app + visual是在 http://codepen.io/emkk/笔/ dGYXJO 的。这个应用程序基本上是从我之前定义的玩家对象数组中创建玩家卡。
我按照点击按钮来实现玩家卡片的排序。我创建了一个< Sort />
组件,呈现所述按钮。我会附加事件监听器,但不知道如何反映在我的< Roster />
组件中。我已经尝试了许多不同的方法与 this.state
,但似乎不能让这个工作。所以请任何帮助实施排序或一般性的建议将被大大的帮助!
class ProfileCard extends React.Component {
render(){
return(
< section className =profile-card>
< figure>
< img src = {this.props.player。 picURL} alt = {this.props.player.Name}>< / img>
< article>
< ul>
< li> {this.props.player .Name}< / li>
< li> {this.props.player.position},#{this.props.player.number}< / li>
< li& this.props.player.Club}< / li>
< li> {this.props.player.Height}({this.props.player.Meters} m)< / li>
< li> {this.props.player.Age}年龄< / li>
< / ul>
< / article>
< / figure>
< / section>
);
}
}
类名称扩展React.Component {
render(){
//存储数据排序版本的
//我实现选择的排序
var sorted = this.props.players.sort();
/ *
*从JSON集合创建播放器卡
* /
var cards = [];
sorted.forEach(function(player){
if(player.year> 2000){
cards.push(< ProfileCard player = {player} />);
}
});
return(< div> {cards}< / div>);
}
}
class Sort extends React.Component {
render(){
return(
< div className =sort < / div>
< h1>
< h1>
< div className =pillid ='age'> className =pillid ='Meters'> Height< / div>
< div className =pillid ='Name'> Name< / div>
< / div>
)
}
}
class SortablePlayerTable extends React.Component {
render(){
/ *
*在花名册前缀
*前缀一些兴趣
* /
var ages = [],heights = [];
this.props.players.forEach(function(player){
if(player.year> 2000){
ages.push(player.Age);
heights.push(player.Meters);
}
});
var avgAge =(ages.reduce((a,b)=> a + b)/ 12).toPrecision(3);
var avgHeights =(heights.reduce((a,b)=> a + b)/ 12).toPrecision(3);
//返回带有统计数据和Roster的页面
return(
< div>
< h1> 2012奥运男子篮球队< / h1&$ $ b< h2>平均年龄:{avgAge} years old< / h2>
< h2>平均身高:6 ft 7 in({avgHeights} m)< / h2>
&排序/>
< Roster
players = {this.props.players}
/>
< / div>
);
}
};
React.render(
< SortablePlayerTable players = {PLAYERS} />
document.getElementById('container')
);
解决方案:
另一件让我失望的事情是,我正在失去访问 this.setState
,不断得到一个 this.setState是不是一个功能
错误。使用ES6箭头函数来对我的处理函数进行词法绑定
可以帮助我。
class ProfileCard extends React.Component {
render(){
return(
< section className =profile-card>
< figure>
< img src = {this.props.player.picURL} alt = {this.props.player.Name}>< / img>
< article>
< ul> ;
< li> {this.props.player.Name}< / li>
< li> {this.props.player.position},#{this.props.player.number }< / li>
< li> {this.props.player.Club}< / li>
< li> {this.props.player.Height}({this.props .player.Meters} m)< / li>
< li> {this.props.player.Age}年龄< / li>
< / ul>
< / article>
< / figure>
< / section>
);
}
}
class花名册扩展React.Component {
render(){
//从排序的动态JSON集合中创建播放器卡
var cards = [];
this.props.players.forEach(function(player){
if(player.year> 2000){
cards.push(< ProfileCard player = {player} /> );
}
});
return(< div> {cards}< / div>);
}
}
class Sort extends React.Component {
sortRoster(field){
var players = this.props.players;
this.props.sortRosterStateBy(field,players);
}
render(){
return(
< div className =sort-section>
< h1>按< / h1> b $ b< div className =pillonClick = {this.sortRoster.bind(this,'Age')}> Age< / div>
< div className =pillonClick = {this .sortRoster.bind(this,'Meters')}> Height< / div>
< div className =pillonClick = {this.sortRoster.bind(this,'Name')}> Name< ; / div>
< div className =pillonClick = {this.sortRoster.bind(this,'position')}>位置< / div>
< div className = onClick = {this.sortRoster.bind(this,'number')}> Number< / div>
< div className =pillonClick = {this.sortRoster.bind(this,'Club' )}> Club< / div>
< / div>
)
}
}
class SortablePlayerTable extends React.Component {
state = {
'players':this.props.players //默认状态
}
sortRosterStateBy =(field,players)=> {
// Sorting ...
var sortedPlayers = players.sort((a,b)=> {
if(a [field]> b [field]){
return 1;
}
if(a [field]< b [field]){
return -1;
}
return 0;
});
//然后调用setState
this.setState({'players':sortedPlayers});
}
render(){
//前缀名前的一些兴趣
var ages = [],heights = [];
this.props.players.forEach(function(player){
if(player.year> 2000){
ages.push(player.Age);
height。 push(player.Meters);
}
});
var avgAge =(ages.reduce((a,b)=> a + b)/ 12).toPrecision(3);
var avgHeight =(heights.reduce((a,b)=> a + b)/ 12).toPrecision(3);
//返回带有统计数据和Roster的页面
return(
< div>
< h1> 2012奥运男子篮球队< / h1&$ $ b< h2>平均年龄:{avgAge} years old< / h2>
< h2>平均身高:6 ft 7 in({avgHeight} m)< / h2>
& Sort player = {this.props.players} sortRosterStateBy = {this.sortRosterStateBy} />
< Roster players = {this.state.players} />
< / div>
);
}
};
ReactDOM.render(
< SortablePlayerTable players = {PLAYERS} />
document.getElementById('container')
);
将功能附加到每个在
< Sort />
中点击它调用父函数 this.props .sortBy()
class Sort extends React.Component {
pre>
sort(field) {
this.props.sortBy(field);
}
render(){
return(
< div className =sort-section>
< h1>按< / h1> b $ b< div className =pillid ='age'onClick = this.sort.bind(this,'age')> Age< / div>
< div className =pillid ='Meters'onClick = this.sort.bind(this,'height')> Height< / div>
< div className =pillid ='Name'onClick = this.sort.bind这个'name')> Name< / div>
< / div>
)
}
}
将此父函数
sortBy
作为道具
从class SortablePlayerTable extends React .Component {
state = {
players:[] //默认状态
}
sortBy(field){
//你的排序算法这里
//它应该按数组中的排序值排序调用sortedPlayers
//然后调用setState
this.setState({
players:sortedPlayers
});
}
render(){
//计算stats
return(
< div>
{/ * some JSX * /}
< Sort sortBy = {sortBy} />
< Roster
players = {this.state.players}
/>
< / div>
);
}
};
现在排序的数组将可用于您的
< Roster />
组件为this.props.players
。直接呈现数组,而不需要在< Roster />
组件中进行任何排序。I'm trying to learn React concepts, especially re: state and dynamic UIs, by coding a small sports roster-like UI. I've included the code below and the whole app + visual is at http://codepen.io/emkk/pen/dGYXJO. This app basically creates player cards from an array of player objects I've defined earlier.
I would like to implement sorting of the player cards upon button click. I've created a
<Sort/>
component that renders the said buttons. I'd attach event listeners but don't know how to have that reflected in my<Roster/>
component. I have tried many different approaches withthis.state
but can't seem to be get this to work. So please any help with implementing sorting or general advice would be much apprieciated!class ProfileCard extends React.Component { render() { return ( <section className="profile-card"> <figure> <img src={this.props.player.picURL} alt={this.props.player.Name}></img> <article> <ul> <li>{this.props.player.Name}</li> <li>{this.props.player.position}, #{this.props.player.number}</li> <li>{this.props.player.Club}</li> <li>{this.props.player.Height} ({this.props.player.Meters} m)</li> <li>{this.props.player.Age} years old</li> </ul> </article> </figure> </section> ); } } class Roster extends React.Component { render() { // Store sorted version of data // Where I'd implement selected sorting var sorted = this.props.players.sort(); /* * Create player cards from JSON collection */ var cards = []; sorted.forEach(function(player) { if (player.year > 2000) { cards.push(<ProfileCard player={player} />); } }); return (<div>{cards}</div>); } } class Sort extends React.Component { render() { return ( <div className="sort-section"> <h1>Sort by</h1> <div className="pill" id='age'>Age</div> <div className="pill" id='Meters'>Height</div> <div className="pill" id='Name'>Name</div> </div> ) } } class SortablePlayerTable extends React.Component { render() { /* * Prefix some interestings stats * before roster */ var ages = [], heights = []; this.props.players.forEach(function(player) { if (player.year > 2000) { ages.push(player.Age); heights.push(player.Meters); } }); var avgAge = (ages.reduce( (a, b) => a + b) / 12).toPrecision(3); var avgHeights = (heights.reduce( (a, b) => a + b) / 12).toPrecision(3); // Return page with stats data and Roster return ( <div> <h1>2012 Olympic Men's Basketball Team</h1> <h2>Average Age: {avgAge} years old</h2> <h2>Average Height: 6 ft 7 in ({avgHeights} m)</h2> <Sort/> <Roster players={this.props.players} /> </div> ); } }; React.render( <SortablePlayerTable players={PLAYERS} />, document.getElementById('container') );
Solution:
Another thing that tripped me up on the way to this was that I was losing access to
this.setState
, kept getting athis.setState is a not a function
error. Using a ES6 arrow function to lexically bindthis
for my handler function rescued me though.class ProfileCard extends React.Component { render() { return ( <section className="profile-card"> <figure> <img src={this.props.player.picURL} alt={this.props.player.Name}></img> <article> <ul> <li>{this.props.player.Name}</li> <li>{this.props.player.position}, #{this.props.player.number}</li> <li>{this.props.player.Club}</li> <li>{this.props.player.Height} ({this.props.player.Meters} m)</li> <li>{this.props.player.Age} years old</li> </ul> </article> </figure> </section> ); } } class Roster extends React.Component { render() { // Create player cards from sorted, dynamic JSON collection var cards = []; this.props.players.forEach(function(player) { if (player.year > 2000) { cards.push(<ProfileCard player={player} />); } }); return (<div>{cards}</div>); } } class Sort extends React.Component { sortRoster(field){ var players = this.props.players; this.props.sortRosterStateBy(field, players); } render() { return ( <div className="sort-section"> <h1>Sort by</h1> <div className="pill" onClick={this.sortRoster.bind(this,'Age')} >Age</div> <div className="pill" onClick={this.sortRoster.bind(this,'Meters')} >Height</div> <div className="pill" onClick={this.sortRoster.bind(this,'Name')} >Name</div> <div className="pill" onClick={this.sortRoster.bind(this,'position')} >Position</div> <div className="pill" onClick={this.sortRoster.bind(this,'number')} >Number</div> <div className="pill" onClick={this.sortRoster.bind(this,'Club')} >Club</div> </div> ) } } class SortablePlayerTable extends React.Component { state = { 'players': this.props.players // default state } sortRosterStateBy = (field, players) => { // Sorting ... var sortedPlayers = players.sort( (a, b) => { if (a[field] > b[field]) { return 1; } if (a[field] < b[field]) { return -1; } return 0; }); // Then call setState this.setState({'players': sortedPlayers}); } render() { // Prefix some interestings stats before roster var ages = [], heights = []; this.props.players.forEach(function(player) { if (player.year > 2000) { ages.push(player.Age); heights.push(player.Meters); } }); var avgAge = (ages.reduce( (a, b) => a + b) / 12).toPrecision(3); var avgHeight = (heights.reduce( (a, b) => a + b) / 12).toPrecision(3); // Return page with stats data and Roster return ( <div> <h1>2012 Olympic Men's Basketball Team</h1> <h2>Average Age: {avgAge} years old</h2> <h2>Average Height: 6 ft 7 in ({avgHeight} m)</h2> <Sort players={this.props.players} sortRosterStateBy={this.sortRosterStateBy}/> <Roster players={this.state.players}/> </div> ); } }; ReactDOM.render( <SortablePlayerTable players={PLAYERS} />, document.getElementById('container') );
解决方案Attach a function to each
<div/>
in<Sort/>
on clicking which it calls a parent functionthis.props.sortBy()
class Sort extends React.Component { sort(field){ this.props.sortBy(field); } render() { return ( <div className="sort-section"> <h1>Sort by</h1> <div className="pill" id='age' onClick=this.sort.bind(this,'age')>Age</div> <div className="pill" id='Meters' onClick=this.sort.bind(this,'height')>Height</div> <div className="pill" id='Name' onClick=this.sort.bind(this,'name')>Name</div> </div> ) } }
Pass this parent function
sortBy
asprops
from your<SortablePlayerTable/>
component.class SortablePlayerTable extends React.Component { state = { players: [] // default state } sortBy(field){ // Your sorting algorithm here // it should push the sorted value by field in array called sortedPlayers // Then call setState this.setState({ players: sortedPlayers }); } render() { // calculate stats return ( <div> {/* some JSX */} <Sort sortBy={sortBy}/> <Roster players={this.state.players} /> </div> ); } };
Now the sorted array will be available to your
<Roster/>
component asthis.props.players
. Render the array directly without applying any sort inside<Roster/>
component.这篇关于React.js - 实现组件的排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!