Adding specific items to a generic component in React

Viewed 306

I have main and common top Navigation Bar (TopMenu) and a body that corresponds to different modules.

/* App.js */

    render() {
        if (this.props.appLoading) return <Container />;
        return (
          <Container className="App" fluid>
            <TopMenu menuStyle={menuStyle} />
            <BodyContainer />
          </Container>
        );
      }

Each module has a bunch of menu items that need to be displayed on the common Top navigation when that module loads.

 /* TopMenu.js */

    render() {
        return (
          <Menu
            fixed="top"
            inverted
            secondary
            stackable
            style={this.props.menuStyle}
          >
            <Menu.Item as={Link} to="/" header>
              <Logo />
            </Menu.Item>

            { /* Module 1 Menu Items */ }

            {this.props.isAuthenticated && this.props.module==='market' && (
              <Menu.Menu position="left">
                <Menu.Item style={{ width: '30rem' }}>
                  <AutoCompleteContainer />
                </Menu.Item>
                <Menu.Item>
                  <Icon name="empty star" />
                </Menu.Item>
                <Menu.Item>
                  <Icon name="line chart" />
                </Menu.Item>
                <Menu.Item>
                  <Icon name="remove bookmark" />
                </Menu.Item>
                <Menu.Item>
                  <Icon name="lock" />
                </Menu.Item>
              </Menu.Menu>
            )}

            { /* Module 2 Menu Items */ }
            { /* Module x Menu Items */ }

            <Menu.Menu position="right">
              {!this.props.isAuthenticated && notAuthenticatedMenuItems}
              {this.props.isAuthenticated && (
                <Menu.Item>
                  <ProfileDropdown onSignOut={this.props.onLogOut} />
                </Menu.Item>
              )}
            </Menu.Menu>
          </Menu>
        );
      }
    }

Clearly, having a common top navigation is making it very difficult to have all the show/hide menu items related to each module in one place. This is because there will be lot of code in one file and also, the navigation will hold the logic for showing/displaying items related to each module, which is against best practices.

My question, is how can I structure the project/code, so that I reuse the common top navigation while each module loads the required menu items when that module loads? Is there a "Extension Point" concept in React where the common top navigation bar provides an extension point for the modules to plug-in their respective items.

1 Answers

You could make the top generic menu as a component and then pass your respective seperate menu items as children to this Navigation component

class TopMenu extends React.Component {
    render() {
        return (
          <Menu
            fixed="top"
            inverted
            secondary
            stackable
            style={this.props.menuStyle}
          >
            <Menu.Item as={Link} to="/" header>
              <Logo />
            </Menu.Item>

            {this.props.children}

            <Menu.Menu position="right">
              {!this.props.isAuthenticated && notAuthenticatedMenuItems}
              {this.props.isAuthenticated && (
                <Menu.Item>
                  <ProfileDropdown onSignOut={this.props.onLogOut} />
                </Menu.Item>
              )}
            </Menu.Menu>
          </Menu>
        );
      }
    }
 }

and use it as

 <Container className="App" fluid>
        <TopMenu menuStyle={menuStyle}>
          { /* Module 1 Menu Items */ }

        {this.props.isAuthenticated && this.props.module==='market' && (
          <Menu.Menu position="left">
            <Menu.Item style={{ width: '30rem' }}>
              <AutoCompleteContainer />
            </Menu.Item>
            <Menu.Item>
              <Icon name="empty star" />
            </Menu.Item>
            <Menu.Item>
              <Icon name="line chart" />
            </Menu.Item>
            <Menu.Item>
              <Icon name="remove bookmark" />
            </Menu.Item>
            <Menu.Item>
              <Icon name="lock" />
            </Menu.Item>
          </Menu
        </TopMenu>
        <BodyContainer />
 </Container>

Similarly you could use it at other places as well

Related