簡體   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