2015-12-17 44 views
6

Próbuję nauczyć się React pojęć, szczególnie w zakresie: stanu i dynamicznych interfejsów użytkownika, kodując mały sportowy interfejs podobny do listy kontaktów. Załączam poniższy kod, a cała aplikacja + visual ma numer http://codepen.io/emkk/pen/dGYXJO. Ta aplikacja w zasadzie tworzy karty graczy z tablicy obiektów graczy, które wcześniej zdefiniowałem.React.js - Wdrażanie sortowania komponentów

Chciałbym wprowadzić sortowanie kart graczy po kliknięciu przycisku. Stworzyłem komponent <Sort/>, który renderuje wymienione przyciski. Dołączyłem detektory zdarzeń, ale nie wiem, jak to odzwierciedlić w moim komponencie <Roster/>. Próbowałem wielu różnych podejść z this.state, ale nie wydaje się, aby to działało. Więc proszę o pomoc przy wdrażaniu sortowania lub ogólnych porad, które byłyby bardzo cenione!

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

Rozwiązanie:

Inną rzeczą, która mnie zadziałał na drodze do tego było to, że utrata dostępu do this.setState, trzymane otrzymuję błąd this.setState is a not a function. Używanie funkcji strzałki ES6 do leksykalnego powiązania funkcji this dla mojej funkcji uchwytu uratowało mnie jednak.

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

Odpowiedz

10

Dołączanie funkcji do każdego <div/> w <Sort/> po kliknięciu którego nazywa funkcji nadrzędnej 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> 
    ) 
    } 
} 

przekazać tę funkcję nadrzędną sortBy jak props z komponentu <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> 
    ); 
    } 
}; 

Teraz posortowanej tablicy będą dostępne dla komponentu <Roster/> jak this.props.players. Renderuj macierz bezpośrednio bez stosowania jakiegokolwiek elementu wewnątrz komponentu <Roster/>.

+0

Dzięki! To zdecydowanie postawiło mnie na właściwej drodze. – Melanchroes