reactjsloopsreact-domreact-dom-server

Looping through route maps in React Main.js


I am using react-router-dom for my blogs. My Main.js looks like

    const Main = () => {
      return (
        <Switch> {/* The Switch decides which component to show based on the current URL.*/}
          <Route exact path='/' component={Home}></Route>
          <Route exact path='/1' component={art1}></Route>
          <Route exact path='/2' component={art2}></Route>
          {/* <Route exact path='/3' component={art3}></Route> */}
        </Switch>
      );
    }

and I want to make it understand automatically as component = "art"+path. How should I go about it?


Solution

  • UPDATED ANSWER

    Code has been further reduced by using dynamic imports with React.lazy. (See initial answer further below for original code)

    import { lazy, Suspense } from "react";
    import { Switch, Route } from "react-router-dom";
    
    const Main = () => {
      return (
        <Switch> {/* The Switch decides which component to show based on the current URL.*/}
          <Route exact path='/' component={Home}></Route>
          <Suspense fallback="">
            {
              [...Array(3).keys()].map((i) => {
                const artComp = lazy(() => import(`./components/Art${i+1}`));
                return (<Route exact path={`/${i+1}`} key={i+1} component={artComp}></Route>);
              })
            }
          </Suspense>
        </Switch>
      );
    }
    

    View updated demo on codesandbox

    What the code does:

    1. Create a Suspense component to wrap the Routes which components will be dynamically generated via React.lazy.

    2. Inside the map function:

    Explanation:

    With React.lazy, you can dynamically import a module and render it into a regular component.

    React.lazy takes a function that calls a dynamic import. This returns a promise which resolves to the imported module.

    Note: the components in the imported modules should be default exports, otherwise the promise resolves to undefined.

    Lazy loading means loading only what is currently needed. As the components will be lazy components, they'll be loaded only when first rendered (i.e. when you click on the corresponding link for the first time).

    Notes:

    For more information, view the React documentation about React.lazy.

    INITIAL ANSWER

    How about this?

    import Art1 from '...';
    import Art2 from '...';
    import Art3 from '...';
    // and so on
    
    const Main = () => {
    
      const artComponents = {
        art1: Art1,
        art2: Art2,
        art3: Art3,
        // and so on
      };
    
      return (
        <Switch> {/* The Switch decides which component to show based on the current URL.*/}
          <Route exact path='/' component={Home}></Route>
          {
            [...Array(3).keys()].map((i) => {
              const artComp = artComponents[`art${i+1}`];
              return (<Route exact path={`/${i+1}`} key={i+1} component={artComp}></Route>)
            })
          }
        </Switch>
      );
    }
    

    What this does:

    1. Import "art"+path components into file

      Note: component name should start with a capital letter.

    2. Store imported components in an object

    3. Create an empty array with 3 empty slots

      Note: replace 3 by the number of "art"+path routes you need to generate.

    4. Access the array's indexes

    5. Create an array with those indexes

    6. For each array index:

    7. Compute the required "art"+path based on the index, and get the matching component from the object in step 2

    8. Return a <Route>, with the path set based on the index and the component set to the matching component above

      E.g. for index 0:

      • artComp will be artComponents[1] a.k.a. Art1
      • path will be /1
      • component will be Art1