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?
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:
Create a Suspense
component to wrap the Routes
which components will be dynamically generated via React.lazy
.
Inside the map
function:
Generate component dynamically
Set the Route's component
property to the above component
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 export
s, 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:
No fallback has been specified for the Suspense
in the answer.
With a Suspense
, you can specify a fallback content (e.g. a loading indicator) to render while waiting for the lazy component to load.
The fallback content can be an HTML string, e.g.
fallback={<div>Loading...</div>}
or a component, e.g.:
fallback={<LoadingIndicator/>}
(21.08.21) React.lazy
and Suspense
are not yet available for server-side rendering. If you want to do this in a server-rendered app, React recommends Loadable Components.
For more information, view the React documentation about React.lazy.
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:
Import "art"+path components into file
Note: component name should start with a capital letter.
Store imported components in an object
Create an empty array with 3 empty slots
Note: replace 3
by the number of "art"+path routes you need to generate.
Access the array's indexes
Create an array with those indexes
For each array index:
Compute the required "art"+path based on the index, and get the matching component from the object in step 2
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