设计模式帮助:如何从单个控制器组件呈现动态视图?

时间:2016-04-21 20:21:47

标签: design-patterns reactjs

我目前有一个包含业务逻辑的组件,具体取决于页面,我想呈现不同的视图。我遇到了麻烦,因为我不确定如何优雅地将控件组件的函数和道具传递给视图组件。

现在,我的解决方案是:

<Controller viewComponent={ViewComponent} />

然后在Controller中进行渲染:

<this.props.viewComponent function1={this.func} function2={this.func2} />

它有效,但令人困惑,我几乎可以肯定它不是最优雅的解决方案。还有克隆的解决方案,但这似乎也是一种黑客攻击。

有没有人对如何解决这个问题有任何见解?

2 个答案:

答案 0 :(得分:1)

您可能有兴趣使用react-router之类的内容。您可以使用react-router执行客户端路由,这将根据访问的URL呈现不同的React组件。

例如,此组件将用于定义您的路线以及将使用哪些组件来表示它们:

<强> index.js

import {render} from 'react-dom';
import {Router, Route, IndexRoute, hashHistory} from 'react-router';
import App from './app';
import Home from './home';
import Account from './account';

render((
    <Router history={hashHistory}>
        <Route path='/' component={App}>
            <IndexRoute component={Home}/>
            <Route path='/account:username' component={Account}/>
        </Route>
    </Router>
), document.getElementById('react-root'));

此组件将用于将道具(例如函数列表)传递给任何动态呈现的组件(通过React.Children呈现):

<强> app.js

import React from 'react';

function getFunctionList() {
    return {
        someFunction() {
            //do something
        },
        someOtherFunction() {
            //do something
        }
    };
}

function renderComponent() {
    return React.Children.map(this.props.children, child =>
        React.cloneElement(child, ...getFunctionList())
    );
}

export default class extends React.Component {
    render() {
        return (
            <div className='wrapper'>
                <nav>
                    <ul>
                        <li><Link to={'/home'}>Home</Link></li>
                        <li><Link to={`/account/foo`}>foo's Account</Link></li>
                    </ul>
                </nav>
                {renderComponent.call(this)}
                <footer></footer>
            </div>
        );
    }
};

以下是访问路线时要向用户显示的组件的一些简单示例:

<强> home.js

import React from 'react';

export default class extends React.Component {
    render() {
        //you could call this.props.someFunction() here
        return (
            <div className='home'>
                Home Page
            </div>
        );
    }
};

<强> account.js

import React from 'react';

export default class extends React.Component {
    const {username} = this.props.params;

    render() {
        return (
            <div className='account'>
                Viewing account for {username}
            </div>
        );
    }
};

我真的认为你最好的办法是做这样的事情。你的问题听起来就像是为了解决而建立反应路由器的那种问题。

如果您愿意,可以将其扩展为使用Redux来跟踪可以管理应用程序状态的单个store。为了使其与react-router保持同步,您还可以使用this library

如果您对此有任何疑问,请与我们联系。

答案 1 :(得分:0)

为什么不这样做:

<Controller> <ViewComponent ... /> </Controller>

在Controller的渲染功能中:

<div> {this.props.children} </div>

更新:如果你想将父函数和state / props传递给子节点,你可以使用React.Children.map函数。

renderChildren = () => {
  React.Children.map(this.props.children, (c) => {
    <c.type
      {...this.props}
      {...c.props}
      someFunction={this.someFunction}
    />
  }
}

<div>
{ this.renderChildren() }
</div>