Search code examples
javascriptreactjsreact-bootstrap

How to use Map in ReactJS in creating routes dynamically?


sample below constant file. I add a column to children propery that contains my component. I don't know if this is okay that I am trying to pass this to my Route element using map so that I can populate the Route in react dynamically.

navLink.js

export const navLinks = [
  {
    id: "manage",
    title: "Manage",
    children: [
        {
            id: 'manage/DevMaintenance',
            title: 'Device Attribute Maintenance',
            component: '<DeviceAttributeMaintenance/>'
        },
        {
            id: 'manage/WaferPieceData',
            title: 'Wafer Piece Data',
            component: '<WaferPieceData/>'
        }
    ]
}
];

manually import those components.

I use them like this but it's not working.

import React from 'react'
import {Navbar, Nav, Container, NavDropdown} from 'react-bootstrap';
import { navLinks } from '../constants/index.js';
import {
    Route,
    Routes,
    Link,
    BrowserRouter,
} from "react-router-dom";

import { DeviceAttributeMaintenance } from '../pages/DeviceAttributeMaintenance.jsx';
import { WaferPieceData } from '../pages/WaferPieceData.jsx';

export const Navigation = () => {
    return (
        <BrowserRouter>
            <Navbar bg="dark" variant="dark" expand="lg">
                <Container>
                    <Navbar.Brand href="#home">Sample</Navbar.Brand>
                    <Navbar.Toggle aria-controls="basic-navbar-nav" />
                    <Navbar.Collapse id="basic-navbar-nav">
                        <Nav className="ms-auto">
                            {navLinks.map((nav, index) => {
                                if (!nav.children) {
                                    return (
                                        <Nav.Link as={Link} to={`${nav.id}`}>{nav.title}</Nav.Link>
                                    );
                                } else {
                                    return (
                                        <NavDropdown title={nav.title} id="basic-nav-dropdown">
                                            {nav.children.map((dropdown, idx) => (
                                                <NavDropdown.Item as={Link} to={`${dropdown.id}`}>{dropdown.title}</NavDropdown.Item>
                                            ))}
                                        </NavDropdown>
                                    );
                                }
                            })}
                        </Nav>
                    </Navbar.Collapse>
                </Container>
            </Navbar>

            <Routes>
                {navLinks.map((nav, index) => {
                    if (!nav.children) {
                        return (
                            <Route path={`${nav.id}`} element={`${nav.component}`} /> 
                        );
                    } else {
                        return (
                            <Route path={`${nav.children.id}`} element={`${nav.children.component}`} />
                        );
                    }
                })}
            </Routes>
        </BrowserRouter>
    )
}

Tried also like this below.

{navLinks.map((nav, index) => {
                if (!nav.children) {
                  return (
                    <Route path={`${nav.id}`} element={`${nav.component}`} />
                    
                  );
                } else {
                  return (
                    {nav.children.map((dropdown, idx) => (
                    <Route path={`${dropdown.id}`} element={`${dropdown.component}`}></Route>
                    ))}
                  );
                 
                }
                })}

but an error will return

errorMsg

I'm expecting to dynamically create routes from an array of constants for us to maintain the app more easily.


Solution

  • Import all related components in "constant.js" file and use them like so:

    import { DeviceAttributeMaintenance } from '../pages/DeviceAttributeMaintenance.jsx';
    import { WaferPieceData } from '../pages/WaferPieceData.jsx';
    
    export const navLinks = [
        {
            id: "manage",
            title: "Manage",
            children: [
                {
                    id: 'manage/DevMaintenance',
                    title: 'Device Attribute Maintenance',
                    component: <DeviceAttributeMaintenance />
                },
                {
                    id: 'manage/WaferPieceData',
                    title: 'Wafer Piece Data',
                    component: <WaferPieceData />
                }
            ]
        }
    ];
    

    You can then add the routes dynamically like so

    <Routes>
        {navLinks.map((nav, index) => {
            if (!nav.children) {
                return (
                    <Route path={nav.id} element={nav.component} /> 
                );
            } else {
                return nav.children.map((child, idx) => (
                    <Route path={child.id} element={child.component} key={child.id}></Route>
                ));
            }
        })}
    </Routes>