2015-12-17 21 views
6

Sto cercando di imparare i concetti di React, in particolare le interfacce utente re: state e dinamiche, codificando una piccola interfaccia utente tipo roster. Ho incluso il codice qui sotto e l'intera app + visual è allo http://codepen.io/emkk/pen/dGYXJO. Questa app crea fondamentalmente carte giocatore da una serie di oggetti giocatore che ho definito in precedenza.React.js - Implementare l'ordinamento dei componenti

Vorrei implementare l'ordinamento delle carte giocatore al clic del pulsante. Ho creato un componente <Sort/> che esegue il rendering dei suddetti pulsanti. Allegherei i listener di eventi ma non so come farlo nel mio componente <Roster/>. Ho provato molti approcci diversi con this.state ma non riesco a farlo funzionare. Quindi, qualsiasi aiuto con l'implementazione di ordinamenti o consigli generali sarebbe molto apprezzato!

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') 
); 

Soluzione:

Un'altra cosa che mi sgambetto sulla strada per questo era che stavo perdendo l'accesso a this.setState, continuato a ottenere un errore di this.setState is a not a function. Tuttavia, l'utilizzo di una funzione freccia ES6 per legare lessicalmente this per la funzione di gestione mi ha salvato.

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') 
); 

risposta

10

associare una funzione a ogni <div/> in <Sort/> il clic che si chiama una funzione di genitore 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> 
    ) 
    } 
} 

passare questa funzione di genitore sortBy come props dal componente <SortablePlayerTable/>.

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> 
    ); 
    } 
}; 

Ora l'array ordinato sarà disponibile per il componente <Roster/> come this.props.players. Renderizza l'array direttamente senza applicare alcun tipo all'interno del componente <Roster/>.

+0

Grazie! Questo sicuramente mi ha messo sulla strada giusta. – Melanchroes