This question related to dynamically importing JSX files into React.
Basically we have one main component that dynamically renders other components based on a structure stored in a database. The dynamic components are stored in a subdirectory "./Components". We statically define the this as:
import CompA from './Components/CompA';
import CompB from './Components/CompB';
var components = {
'CompA': CompA,
'CompB': CompB
}
and we render them using:
var type = 'CompA'
var Component = components[type];
...
<Component />
While this works fine, it is a bit too static for us. We have 100+ components (CompA/CompBs) and statically define them does not work.
Is it possible to import all JSX files in "./Compontents" and populate the components-array?
And, what would be really (really) nice would be if we could send the "./Components" path as a prop to the main components. And the main component would use this path to import the .jsx files. Like this:
<MainComponent ComponentPath="./SystemComponents">
Would use "./SystemComponents" as path for .JSX files and:
<MainComponent ComponentPath="./UserComponents">
Would use "./UserComponents" as import path.
What about having a components/index.js with contents:
export CompA from "./comp_a";
export CompB from "./comp_b";
Then you do:
import * as Components from "./components"
then you would use as:
<Components.CompA />
<Components.CompB />
...
Hope this helps.
I doubt you can load anything when sending path through component props, loading of the file should then happen inside the React component lifecycle methods which is not something I would recommend.
To complement @gor181's answer, I can add that export
s must be this way:
export { default as CompA } from "./comp_a"; export { default as CompB } from "./comp_b";
Hope this might be helpful.
As of React 16.6.0 , we can lazy-load components and invoke them on-demand.
The Routing
// We pass the name of the component to load as a param
<Switch>
…
<Route path="/somewhere/:componentName" component={MyDynamicComponent} />
</Switch>
views/index.js
import { lazy } from 'react';
const SomeView = lazy(() => import('./SomeView'));
const SomeOtherView = lazy(() => import('./SomeOtherView'));
export { SomeView, SomeOtherView };
MyDynamicComponent.js
import React, { Suspense, Component } from 'react';
import { PropTypes } from 'prop-types';
import shortid from 'shortid'; // installed separately via NPM
import * as Views from './views';
class MyDynamicComponent extends Component {
render() {
const {
match: {
params: { componentName },
},
} = this.props;
const Empty = () => <div>This component does not exist.</div>;
const dynamicComponent = (() => {
const MyComponent = Views[`${componentName}View`]
? Views[`${componentName}View`]
: Empty;
return <MyComponent key={shortid.generate()} />;
})();
return (
<>
<Suspense fallback={<div>Loading…</div>}>{dynamicComponent}</Suspense>
</>
);
}
}
MyDynamicComponent.propTypes = {
match: PropTypes.shape({
params: PropTypes.shape({
componentName: PropTypes.string.isRequired,
}),
}),
};
export default MyDynamicComponent;
Usage
{items.map(item => (
<NavLink to={`/somewhere/${item.componentName}`}>
{item.name}
</NavLink>
))}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.