2016-09-23 4 views
1

Ich bin eine große Anwendung Architect und bin auf einem React Routing Problem hamstrung. Ich würde gerne wissen, wie man diesen Routing/Requisiten/Params- Konflikt durcharbeitet.Große React Application Structure

Hier ist die grundlegende Vorgehensweise: Verwendung reagieren-Router

Login -> 
    Choose classroom (get classroom._id) -> 
    Load BaseLayout (this retrieves the classroom from the DB) -> 
     Load RosterLayout (or any other subdivision of the application (schedule, photos, etc.) 

Da jede Seite des Klassenzimmers (Zeitplan, Roster, etc.) ist es Mini-Anwendung besitzen ist, ich glaube, ich würde diese Komponenten-Layout laden. Allerdings kann ich nicht herausfinden, wie es zu strukturieren, so dass ich die classroom geladen innerhalb der BaseLayout Komponente innerhalb der untergeordneten Komponenten verwenden kann. In diesem Beispiel habe ich versucht, die _id über URL zu übergeben, aber dann muss ich noch das Klassenzimmer wieder abrufen, die nicht wie eine gute Architektur aussieht und ich werde classroom_loading nicht verfügbar haben, um zu wissen, wenn es fertig ist. Gibt es neben URL-Parametern eine bessere oder andere Möglichkeit, dieses Szenario zu behandeln? Kann ich Requisiten an eine über react-router geladene Kindkomponente weitergeben?

Hier ist der Grundcode:

Meteor.startup(() => { 
    render((
     <Router history={browserHistory}> 
      <Route path="/classroom/:classroomId" component={BaseLayoutContainer}> 
       <Route path="roster" component={RosterLayout} /> 
      </Route> 
     </Router> 
    ), document.getElementById('app')); 
}); 



class BaseLayout extends React.Component { 

    render() { 
     return(
      <div id="base"> 
       <div id="headerContainer"> 

       </div> 
       <div id="navContainer"> 
        <div className="classroomHeader"> 
         {this.props.classroom_loading ? 
          <h3>loading...</h3> : 
          <h2>{this.props.classroom.name}</h2> 
         } 
        </div> 
       </div> 
       <div id="bodyContainer"> 
        {this.props.children} 
       </div> 
      </div> 
     ) 
    } 
} 
export default BaseLayoutContainer = createContainer((params) => { 
    let classroom_loading = Meteor.subscribe("classroom.byId", params.params.classroomId); 

    return { 
     currentUser: Meteor.user(), 
     classroom_loading: !classroom_loading.ready(), 
     classroom: Classrooms.findOne({}), 
    }; 
}, BaseLayout); 


export class RosterLayout extends React.Component { 

    render() { 

     return (
      <div id="rosterLayout"> 
       {this.props.children_loading ? 
        <span>loading...</span> : 
        <ul> 
         {this.props.children.map((child) => { 
          return <li>child.name</li>; 
         })} 
        </ul> 
       } 
      </div> 
     ); 
    } 
} 
export default RosterLayoutContainer = createContainer((params) => { 
    let children_loading = Meteor.subscribe("children.byClassroom", params.params.classroomId); 

    return { 
     children_loading: !children_loading.ready(), 
     children: Children.findOne({}), 
    }; 
}, RosterLayout); 

Antwort

1

ich eine große Lösung dank gefunden habe in dem #reactiflux Server der Zwietracht @slightlytyler. Danke Tyler!

Statt blind Kinder auf das Baselayout wie das Laden:

<div id="bodyContainer"> 
    {this.props.children} 
</div> 

... Sie können das eingehende Kind klonen und fügen Sie Ihre eigenen Requisiten, um es, das funktionierte perfekt in diesem Szenario.

<div id="bodyContainer"> 
    {React.Children.map(this.props.children, (
     return React.cloneElement(child, { 
      classroom_loading: this.props.classroom_loading, 
      classroom: this.props.classroom 
     }); 
    })} 
</div>