Dovrebbe esserci un contenitore che associ i nomi dei componenti a tutti i componenti che dovrebbero essere usati in modo dinamico. Le classi di componenti devono essere registrate in un contenitore perché in un ambiente modulare non esiste altrimenti un unico posto in cui sia possibile accedervi. Le classi componenti non possono essere identificate dai loro nomi senza specificarle esplicitamente perché la funzione name
è ridotta al minimo in produzione.
Mappa dei componenti
Può essere un semplice oggetto:
class Foo extends React.Component { ... }
...
const componentsMap = { Foo, Bar };
...
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;
O Map
istanza:
const componentsMap = new Map([[Foo, Foo], [Bar, Bar]]);
...
const DynamicComponent = componentsMap.get(componentName);
L'oggetto semplice è più adatto perché beneficia della stenografia della proprietà.
Modulo a botte
Un modulo a botte con esportazioni denominate può fungere da tale mappa:
// 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/>;
Funziona bene con una classe per stile di codice del modulo.
Decoratore
I decoratori possono essere usati con componenti di classe per lo zucchero sintattico, ciò richiede comunque di specificare esplicitamente i nomi delle classi e registrarli in una mappa:
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'
...
}
Un decoratore può essere utilizzato come componente di ordine superiore con componenti funzionali:
const Bar = props => ...;
Bar.displayName = 'Bar';
export default dynamic(Bar);
Anche l'uso di proprietà non standarddisplayName
anziché casuali è utile per il debug.
{...this.props}
utile anche passare in modo trasparente oggetti di scena ai componenti sottotipati dal genitore. Tiporeturn <MyComponent {...this.props} />