Jon Harding
Jon Harding

Reputation: 4946

Dynamically build routes using react-router

I'm building an application that will call out to an API prior to bootstrapping React. This API will tell me which features I need to load based on the user's subscription.

The API will return an array of objects with the pattern outlined below

links: [
    {
        label: 'Payment Reconciliation',
        component: './components/_paymentReconciliation/paymentReconciliationPage',
        url: '/paymentreconciliation'
    },
    {
        label: 'Device Integration',
        component: './components/_deviceIntegration/deviceIntegrationPage',
        url: '/deviceintegration'
    }
]

It's easy enough to map the links to produce dynamic Routes

export default function Routes() {
    let featureRoutes = config.FEATURES.links.map((menuItem, i) => {
        return (
            <Route path={menuItem.url} component={require(menuItem.component).default} key={i} />
        )
    });
    return (<div>
        <Route exact path="/" component={LandingPage} />
        {featureRoutes}
    </div>
    )
}

This obviously isn't working. I'm struggling figuring out how to not need an import statement for every possible Component that might be loaded. Also should the API be returning the path to the component or just the component name? I've seen examples using something like handler={require(PathToComponent)} That hasn't proven to work either.

Any help here would be appreciated

Upvotes: 1

Views: 1128

Answers (2)

Cory House
Cory House

Reputation: 15045

ES imports must be statically analyzable, so you can't dynamically require them. Instead, you can use a CommonJS style import to dynamically require files:

var myFile = require('myFile');

Combine that with the route-config approach, and you're all set.

You can see an example of this in the documentation module of this Pluralsight course: Creating Reusable React Components

Upvotes: 1

Stephen L
Stephen L

Reputation: 2339

Try requiring your path to the components to get a reference to that component.

export default function Routes() {
    let featureRoutes = config.FEATURES.links.map((menuItem, i) => {
        return (
            <Route path={menuItem.url} component={require(menuItem.component).default} key={i} />
        )
    });
    return (<div>
        <Route exact path="/" component={LandingPage} />
        {featureRoutes}
    </div>
    )
}

Depending on how react-router implemented their component function this code might be a little off. You can always render a react component using require with React.createElement(require('./Component').default)

Upvotes: 2

Related Questions