2016-09-23 78 views
1

我正在构建一个大型应用程序,并且对反应路由问题感到不安。我很想知道如何处理这个路由/道具/参数冲突。大反应应用程序结构

下面是基本过程:

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.) 

由于教室(日程安排,名册等)的每个页面都是它自己的迷你应用程序,我想我会加载使用反应路由器的布局组件。但是,我无法弄清楚如何构建它,以便我可以使用子组件内的BaseLayout组件内部加载的classroom。在这个例子中,我试过通过URL传递_id,但是我仍然需要再次检索教室,这看起来不像是好的体系结构,我不知道classroom_loading何时准备就绪。除了URL参数外,是否有更好或不同的方式来处理这种情况?我可以将道具传递给通过反应路由器加载的子组件吗?

这里的基本代码:

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

回答

1

我已经找到了一个很好的解决方案感谢不和谐的#reactiflux服务器@slightlytyler。谢谢泰勒!

而不是盲目地加载带孩子到的baselayout是这样的:

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

...你可以克隆传入的孩子和追加自己的道具吧,在这种情况下完美地工作。

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