Dynamic Rendering Of React Components Based On External Data

Viewed 25

I want your help, I wanna a method to render pages components with routing but i want a method to do that using an external array (like routes here) and map() method not to hardcoded every route.

import React from 'react'
import {BrowserRouter as Router,Routes, Route} from 'react-router-dom'

 const routes = [
    {
      name: 'home',
      path: '/',
      componentName: 'Home'
    },
    {
      name: 'about',
      path: '/about',
      componentName: 'About'
    },
    {
      name: 'contact',
      path: '/contact',
      componentName: 'Contact'
    }
]
class App extends React.Component {
    render() {
    const nav = this.routes.map((route, i) => 
    <route key={i} path={route.path} element={<{`${route.componentName}`} /* Here is the issue I know this isn't work but i want a method to do the same thing */ /> }/>
)

return (
  <Router>
    <div className='App'> 
      <Routes>{nav}</Routes>
    </div>
  </Router>
)
  } 
}```
2 Answers

please Change <route key={i} path={route.path} /> to <Route key={i} path={route.path} /> maybe typo mistake Route

The issue is that you can't fill the tag in with a string, it needs to be an actual React component reference. You need to import the components you want to render on the routes.

Example:

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from '../pages/Home';
import About from '../pages/About';
import Contact from '../pages/Contact';

const routes = [
  {
    name: 'home',
    path: '/',
    Component: Home // <-- reference imported component
  },
  {
    name: 'about',
    path: '/about',
    Component: About
  },
  {
    name: 'contact',
    path: '/contact',
    Component: Contact
  }
];

class App extends React.Component {
  render() {
    const nav = routes.map(({ path, Component }) => (
      <Route // <-- render Route component
        key={path}
        path={path}
        element={<Component /> } // <-- pass Component to element as JSX
      />
    ));

    return (
      <Router>
        <div className='App'> 
          <Routes>{nav}</Routes>
        </div>
      </Router>
    )
  } 
}

Also, react-router-dom@6 effectively has a React hook to do exactly this. If you are open to using React function components then I suggest using the useRoutes hook instead.

The useRoutes hook is the functional equivalent of <Routes>, but it uses JavaScript objects instead of <Route> elements to define your routes. These objects have the same properties as normal <Route> elements, but they don't require JSX.

The return value of useRoutes is either a valid React element you can use to render the route tree, or null if nothing matched.

Example:

import React from 'react';
import { BrowserRouter as Router, Routes, Route, useRoutes } from 'react-router-dom';
import Home from '../pages/Home';
import About from '../pages/About';
import Contact from '../pages/Contact';

const routes = [
  {
    path: '/',
    element: <Home />
  },
  {
    path: '/about',
    element: <About />
  },
  {
    path: '/contact',
    element: <Contact />
  }
];

const App = () => {
  const appRoutes = useRoutes(routes);

  return (
    <div className='App'>
      {appRoutes}
    </div>
  ); 
}

Wrap the App component in the Router so App can use the useRoutes hook.

<Router>
  <App />
</Router>
Related