React.js - 实现组件的排序 [英] React.js - Implementing sorting of components

查看:208
本文介绍了React.js - 实现组件的排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习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 {
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>

}
}
pre>

将此父函数 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 with this.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 a this.setState is a not a function error. Using a ES6 arrow function to lexically bind this 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 function 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>
    )
  }
}

Pass this parent function sortBy as props 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 as this.props.players. Render the array directly without applying any sort inside <Roster/> component.

这篇关于React.js - 实现组件的排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆