繁体   English   中英

React Shell 组件支持传入路由的组件

[英]React Shell Component Supporting Components Passed In to Routes

再会,

任务

我有一个包含大约 42 个“模块”或服务的应用程序。 每项服务看起来都是统一的,但具有独特的内容。 我正在尝试设计可以减少或消除重复结构代码的 React 组件。 我在正确的轨道上,但可以使用一些指示或建议来了解如何将我所拥有的东西提升到一个新的水平。

语境

我已经承诺了迄今为止我所拥有的。 这个项目是公开的,可以在这里找到: https : //dev.azure.com/Red-Expanse/maelstrom-ui-web-react (create-components 分支)

注意:我的每个显示组件都有一个容器组件,因此我可以调整每个组件的布局,使其与组件的外观和感觉分开。

我想做的事

下面是每个服务的外观示例。 标题和菜单项的服务名称及其目标路径我可以开始工作。 这是我面临挑战的目标组件的实际显示。

+----------------------------------------------+
|Service Header                                |
+---------+------------------------------------+
|Service  |  Service Menu Content              |
| Menu    |  (Content shown here depends       |
|         |      on menu selected.)            |
|  Browse |                                    |
|  New    |                                    |
|  Map    |                                    |
+---------+------------------------------------+

为了实现上述目标,我有以下组件:

服务内容容器组件

由 Service-Shell.component(如下)用于显示路由组件。 这只是一个容器组件,因此我可以独立于其中显示的组件的外观来控制显示和位置。

export const ServiceContentContainer = (props:any) => {
    return <Paper>{props.children}</Paper>;
}

服务外壳组件

这是我之前尝试设计此应用程序的突破。 这是一个组件,需要为每个模块配置一堆道具。 理想情况下,我希望能够传入多个组件并将它们显示在 shell 的 <Route ...> 组件中。

export const ServiceShell = (props:any) => {
    return <Grid container spacing={2}>
        <Grid item sm={12}>
            <ServiceHeaderContainer><ServiceHeader serviceName={props.serviceName} /></ServiceHeaderContainer> 
        </Grid>
        <Grid item sm={3}>
            <ServiceMenuContainer><ServiceMenu serviceMenuChoices={props.serviceMenuChoices} /></ServiceMenuContainer>    
        </Grid>
        <Grid item sm={9}>
            <ServiceContentContainer>
                <Route exact path={props.serviceDashboardPath} component={props.serviceDashboardComponent} />
                <Route exact path={props.serviceDashboardPath} component={props.serviceDashboardComponent} />
                <Route exact path={props.serviceDashboardPath} component={props.serviceDashboardComponent} />
                <Route exact path={props.serviceDashboardPath} component={props.serviceDashboardComponent} />
            </ServiceContentContainer>    
        </Grid>
        <Grid item sm={12}>
            <ServiceFooterContainer><ServiceFooter /></ServiceFooterContainer>            
        </Grid>
    </Grid>;
}

ActivityLog-Service.component

这个组件只是我拥有的 42 个左右的模块之一。 所有这些都是显示一个 ServiceShell(上图)组件并传入所有 props 来为这个特定组件配置通用 shell。 理想情况下,我想在这里将特定于该模块的几个组件传递给 shell,并将它们显示在 shell 中的正确路径中。

import { ServiceShell } from '../../app/service/shell/service-shell.component';

export const ActivityLogService = (props: any) => {
    const bc = () => <h1>Testing</h1>
    
    return <ServiceShell serviceName='Activity Log' serviceBrowseComponent={bc} />;
}

你可以看到我是如何尝试解决这个问题的,但组件没有显示。 我很感激一些关于如何最好地解决这个问题的指导,如果这可能的话。 有没有更好的方法来设计它以实现几乎没有代码重复? 过去是代码重复杀死了我。 在 42 个左右的不同地方调整布局并不好玩。

提前感谢您的时间和想法。


杰森

jas@red-expanse.com

知道了。 这是代码。

服务外壳组件

export const ServiceShell = (props: any) => {
    return <Grid container spacing={2}>
        <Grid item sm={12}>
            <ServiceHeaderContainer><ServiceHeader serviceName={props.serviceName} /></ServiceHeaderContainer> 
        </Grid>
        <Grid item sm={3}>
            <ServiceMenuContainer><ServiceMenu serviceMenuItems={props.serviceMenuItems} /></ServiceMenuContainer>    
        </Grid>
        <Grid item sm={9}>
            <ServiceContentContainer>
                <Switch>
                    <Route exact path='/activitylog' component={props.comp1} />
                    <Route path='/activitylog/browse' component={props.comp2} />
                </Switch>
            </ServiceContentContainer>    
        </Grid>
        <Grid item sm={12}>
            <ServiceFooterContainer><ServiceFooter /></ServiceFooterContainer>            
        </Grid>
    </Grid>;

[新增] Service-Menu.component

export const ServiceMenu = (props: any) => {
    const { push } = useHistory()

    function handleClick(event: any) {
        console.log(event.target.id);
        let path = '';
        let id = '';
        let service = '';
        let str = event.target.id;
        var fields = str.split(',');
        id = fields[0];
        service = fields[1];

        switch (id) {
            case 'dashboard':
                path = '/' + service;
                break;
            case 'browse':
                path = '/' + service + '/browse';
                break;
            case 'new':
                path = '/' + service + '/new';
                break;
            case 'map':
                path = '/' + service + '/map';
                break;
        }

        console.log(path);
        push(path);
    }

    const menu = props.serviceMenuItems.map(function (item: any, i: any) {
        let csv = item.id + ',' + item.service;
        return <Button key={i} id={csv} className='btn-app-menu' onClick={handleClick}>{item.caption}</Button>;
    })

    return <ServiceMenuContainer>{menu}</ServiceMenuContainer>
}

ActivityLog.component

export const ActivityLogService = () => {
    const bc = () => <h1>Testing</h1>
    const bd = () => <h2>More?</h2>

    let menuDashboard = {
        caption: 'Dashboard',
        id: 'dashboard',
        service: 'activitylog'
    }

    let menuBrowse = {
        caption: 'Browse',
        id: 'browse',
        service: 'activitylog'
    }

    let menuItems = [menuDashboard, menuBrowse]

    return <ServiceShell
        serviceName='Activity Log'
        comp1={bc}
        comp2={bd}
        serviceMenuItems={menuItems} />
        }

Service-Container.component [未更改] [未显示]

不适用

完整代码将在 Azure 的 DevOps 站点上提供/将在之前提供的链接中提供。 谢谢。


杰森

jas@red-expanse.com

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM