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

由于教室的每一页(时间表、花名册等)都是它自己的迷你应用程序,我想我会使用 react-router 加载这些布局组件。但是,我无法弄清楚如何构造它,以便我可以在子组件内部使用组件内部的classroom加载。BaseLayout在此示例中,我尝试传递_idvia URL,但我仍然需要再次检索教室,这似乎不是好的架构,而且我无法classroom_loading知道它何时准备就绪。除了 URL 参数之外,还有更好或不同的方法来处理这种情况吗?我可以将道具传递给通过 react-router 加载的子组件吗?

这是基本代码:

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

1 回答 1

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>
于 2016-09-23T21:50:30.950 回答