私はReactの概念、特にre:状態と動的UIを、小さなスポーツ名簿のようなUIをコーディングすることで学習しようとしています。以下のコードを含め、アプリ全体とビジュアルはat 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')
);
ソリューション:
これに至るまでに私をつまずかせたもう1つのことは、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')
);
_<div/>
_の各_<Sort/>
_に、親関数を呼び出すthis.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>
)
}
}
_
この親関数sortBy
を_<SortablePlayerTable/>
_コンポーネントからprops
として渡します。
_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>
);
}
};
_
これで、並べ替えられた配列が_<Roster/>
_コンポーネントで_this.props.players
_として使用できるようになります。 _<Roster/>
_コンポーネント内で並べ替えを適用せずに、配列を直接レンダリングします。