我正在尝试通过编写一个类似体育名册的小型 UI 来学习 React 概念,尤其是 re: state 和动态 UI。我已经包含了下面的代码,整个应用程序 + 视觉效果位于http://codepen.io/emkk/pen/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} 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')
);
解决方案:
在此过程中让我绊倒的另一件事是我无法访问this.setState
,不断收到this.setState is a not a function
错误消息。不过,使用 ES6 箭头函数在词法上绑定this
我的处理程序函数拯救了我。
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')
);