There should be a container that maps component names to all components that should be used dynamically. Component classes must be registered in the container because in a modular environment there is no single place where they could be accessed. Component classes cannot be identified by their names without explicitly specifying them, since the name function is minimized during production.
Component Map
This could be a simple object:
class Foo extends React.Component { ... } ... const componentsMap = { Foo, Bar }; ... const componentName = 'Fo' + 'o'; const DynamicComponent = componentsMap[componentName]; <DynamicComponent/>;
Or a Map instance:
const componentsMap = new Map([[Foo, Foo], [Bar, Bar]]); ... const DynamicComponent = componentsMap.get(componentName);
A simple object is more appropriate because it benefits from a reduction in properties.
Barrel module
A trunk module with named export can act as such a map:
// Foo.js export class Foo extends React.Component { ... } // dynamic-components.js export * from './Foo'; export * from './Bar'; // some module that uses dynamic component import * as componentsMap from './dynamic-components'; const componentName = 'Fo' + 'o'; const DynamicComponent = componentsMap[componentName]; <DynamicComponent/>;
This works well with one class per module code style.
decorator
Decorators can be used with class components for syntactic sugar; for this, you still need to explicitly specify class names and register them in the map:
const componentsMap = {}; function dynamic(Component) { if (!Component.displayName) throw new Error('no name'); componentsMap[Component.displayName] = Component; return Component; } ... @dynamic class Foo extends React.Component { static displayName = 'Foo' ... }
The decorator can be used as a component of a higher order with functional components:
const Bar = props => ...; Bar.displayName = 'Bar'; export default dynamic(Bar);
Using a custom displayName instead of a random property also helps debugging.
estus Apr 21 '19 at 7:08 2019-04-21 07:08
source share