简体   繁体   English

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

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

Good day,再会,

Task任务

I have an app with about 42 or so "modules" or services.我有一个包含大约 42 个“模块”或服务的应用程序。 Each service will appear uniform but have unique content.每项服务看起来都是统一的,但具有独特的内容。 I'm trying to design React components that will reduce or eliminate duplicate structural code.我正在尝试设计可以减少或消除重复结构代码的 React 组件。 I'm on the right track, but could use a few pointers or suggestions for how to take what I have to the next level.我在正确的轨道上,但可以使用一些指示或建议来了解如何将我所拥有的东西提升到一个新的水平。

Context语境

I've committed what I have have so far.我已经承诺了迄今为止我所拥有的。 This project is public and can be found here: https://dev.azure.com/Red-Expanse/maelstrom-ui-web-react (create-components branch)这个项目是公开的,可以在这里找到: https : //dev.azure.com/Red-Expanse/maelstrom-ui-web-react (create-components 分支)

Note: I have a container component for each of my display components so I can tweak the layout of each component separate from the look and feel of the component.注意:我的每个显示组件都有一个容器组件,因此我可以调整每个组件的布局,使其与组件的外观和感觉分开。

What I Want to Do我想做的事

Here is an example of how each service should look.下面是每个服务的外观示例。 The service name for the header and the menu items along with their target paths I can get working.标题和菜单项的服务名称及其目标路径我可以开始工作。 It's the actual display of the target components that I'm challenged.这是我面临挑战的目标组件的实际显示。

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

To make the above happen, I have the following components:为了实现上述目标,我有以下组件:

Service-Content-Container.component服务内容容器组件

Used by Service-Shell.component (below) to display route components.由 Service-Shell.component(如下)用于显示路由组件。 This is just a container component so I can control the display and position separate from the look-and-feel of the components displayed within.这只是一个容器组件,因此我可以独立于其中显示的组件的外观来控制显示和位置。

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

Service-Shell.component服务外壳组件

This is the breakthrough I had from previous attempts to design this application.这是我之前尝试设计此应用程序的突破。 It's one component that takes a bunch of props to configure for each module.这是一个组件,需要为每个模块配置一堆道具。 Ideally, I want to be able to pass in several components and display them in the <Route ...> components in the shell.理想情况下,我希望能够传入多个组件并将它们显示在 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 ActivityLog-Service.component

This component is but one of the 42 or so modules I have.这个组件只是我拥有的 42 个左右的模块之一。 All this does is show a ServiceShell (above) component and pass in all the props to configure the generic shell for this particular component.所有这些都是显示一个 ServiceShell(上图)组件并传入所有 props 来为这个特定组件配置通用 shell。 Ideally, here I want to pass in several components specific to this module to the shell and have them displayed in the correct route in the 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} />;
}

You can see how I've tried to approach this, but the components don't show.你可以看到我是如何尝试解决这个问题的,但组件没有显示。 I would appreciate some guidance on how best to approach this and if this is even possible.我很感激一些关于如何最好地解决这个问题的指导,如果这可能的话。 Is there a better way to design this to achieve little to no code duplication?有没有更好的方法来设计它以实现几乎没有代码重复? It's the code duplication that has killed me in the past.过去是代码重复杀死了我。 Tweaking the layout in 42 or so different places is not fun.在 42 个左右的不同地方调整布局并不好玩。

Thank you in advance for your time and thoughts.提前感谢您的时间和想法。


Jason杰森

jas@red-expanse.com jas@red-expanse.com

Got it.知道了。 Here is the code.这是代码。

Service-Shell.component服务外壳组件

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

[New] Service-Menu.component [新增] 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 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 [Unchanged] [Not Shown] Service-Container.component [未更改] [未显示]

NA不适用

The full code is/will be available on Azure's DevOps site at the link previously provided.完整代码将在 Azure 的 DevOps 站点上提供/将在之前提供的链接中提供。 Thanks.谢谢。


Jason杰森

jas@red-expanse.com jas@red-expanse.com

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

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