ReactJS calcola lo stato sulla modifica ai componenti dei puntelli in seguito a ri-rendering genitore

Ho un'applicazione di esempio che sto usando per imparare ReactJS.

È insieme nidificato di componenti di dettaglio master. C'è un elenco di città, si fa clic su una città e alcuni dettagli della città vengono visualizzati insieme ad un elenco di routes di autobus della città. Quando si fa clic su un path di autobus viene visualizzato un certo dettaglio (fairly pathetic 🙂 del path del bus.

Ecco un violino

I dati sono tutti contenuti in alcuni arrays e ci sono due funzioni di supporto dati, ma questo è solo per renderlo semplice e passerò i dati alle chiamate AJAX più tardi.

Se si guarda il violino vedrà che cliccando su una città aggiornerà correttamente i dettagli della città e l'elenco degli itinerari di autobus e cliccando su una rotta di autobus visualizza correttamente i dettagli di tale itinerario. Il problema è che mentre fai clic su una città diversa aggiorna i routes di autobus della città, non visualizza la prima linea di autobus della città.

Ecco il problema: penso che il componente CityBusRoutes deve ricalcolare / aggiornare lo stato ma non so come / where farlo. CityBusRoutes viene fornito un cityid e quindi prepara un elenco di routes e penso che dovrebbe cambiare lo stato per memorizzare la prima rotta come path selezionato. Inizialmente il luogo logico sembra essere nel metodo di rendering, ma questo è ovviamente sbagliato.

Vi preghiamo di submit qualsiasi consiglio o link ai docs circa il miglioramento del design ecc.

Ecco il codice:

 <!DOCTYPE html> <html> <head> <title></title> <style type="text/css"> li{ cursor: pointer; } </style> </head> <body> <div id="app"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/react.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/JSXTransformsr.js"></script> <script type="text/jsx"> var cityListing = [ {id: 1, name: 'Rome', desc: 'Capital of Italy'}, {id: 2, name: 'London', desc: 'Capital of UK'}, {id: 3, name: 'Washington', desc: 'Capital of USA'} ]; var cityBuses = [ { cityid: 1, routes: [ {id: 707, desc: 'Rome to Beach'}, {id: 717, desc: 'Beach to Rome'}, {id: 708, desc: 'Rome to Naples'}, {id: 718, desc: 'Naples to Rome'} ] }, { cityid: 2, routes: [ {id: 801, desc: 'London to Beach'}, {id: 811, desc: 'Beach to London'}, {id: 802, desc: 'London to Manchester'}, {id: 812, desc: 'Manchester to London'} ] }, { cityid: 3, routes: [ {id: 901, desc: 'Washington to Beach'}, {id: 911, desc: 'Beach to Washington'}, {id: 902, desc: 'Washington to New York'}, {id: 912, desc: 'New York to Washington'} ] } ]; function findCityBusRoutes(cityid){ for(var i = 0; i < cityBuses.length; i++){ if(cityBuses[i].cityid === cityid) return cityBuses[i]; } return null; } function findBusRouteDetails(routeid){ var c, i, routes; if(typeof routeid !== 'number') routeid = parseInt(routeid); for(var c=0; c < cityBuses.length; c++){ routes = cityBuses[c].routes; for(var i=0; i < routes.length; i++){ if(routes[i].id === routeid){ return "Take a scenic bus trip from " + routes[i].desc + '(' + routes[i].id + ')'; } } } return null; } var CityList = React.createClass({ selectCity: function(citylistitem){ this.setState( {selectedCity: citylistitem} ); }, getInitialState: function(){ return {selectedCity: cityListing[0]}; }, render: function(){ var listItems = cityListing.map(function(item){ return <CityListItem key={item.id} data={item} onClick={this.selectCity} /> }, this); return( <div> <ul>{listItems}</ul> <CityDetail data={this.state.selectedCity} /> </div> ); } }); var CityListItem = React.createClass({ clickItem: function(e){ this.props.onClick(this.props.data); }, render: function(){ return ( <li onClick={this.clickItem}>{this.props.data.name}</li> ) } }); var CityDetail = React.createClass({ render: function(){ return( <div> <h3>City of {this.props.data.name}</h3> <p>{this.props.data.desc}</p> <CityBusRoutes data={this.props.data} /> </div> ); } }); var CityBusRoutes = React.createClass({ clickBusRoute: function(e){ this.setState({ routeid: e.currentTarget.getAttribute('data-routeid')}); }, getInitialState: function(){ var cityRoutes = findCityBusRoutes(this.props.data.id); return {routeid: cityRoutes.routes[0].id}; }, render: function(){ var cityRoutes = findCityBusRoutes(this.props.data.id); var routeItems = cityRoutes.routes.map(function(route){ return ( <li data-routeid={route.id} onClick={this.clickBusRoute} >Route: {route.id}, Description: {route.desc}</li> ) }, this); return( <div> <h3>{this.props.data.name} City Bus Routes</h3> <ul>{routeItems}</ul> <CityBusRouteDetail routeid={this.state.routeid}/> </div> ); } }); var CityBusRouteDetail = React.createClass({ render: function(){ var rd = findBusRouteDetails(this.props.routeid); return( <div> <h5>Route Details</h5> <p>{rd}</p> </div> ); } }); React.render(<CityList />, document.getElementById('app')); </script> </body> </html> 

Ok così ho trovato la risposta-Aggiungere il metodo componentWillReceiveProps() al mio componente CityBusRoutes è quello che cercavo. Fondamentalmente dà un posto per calcolare un nuovo stato quando i componenti dei puntelli cambiano.

 componentWillReceiveProps: function(nextProps){ var cityRoutes = findCityBusRoutes(nextProps.data.id); this.setState({routeid: cityRoutes.routes[0].id}); } 

Ecco i relativi React Documenti

Ecco il violino da lavoro

Ancora essere molto felice di ricevere commenti sul disegno sopra

componentWillMount & componentWillReceiveProps è un buon modo per affrontare questi problemi