Estoy tratando de renderizar dinámicamente los componentes en función de su tipo.
Por ejemplo:
var type = "Example"; var ComponentName = type + "Component"; return <ComponentName />; // Returns <examplecomponent /> instead of <ExampleComponent />Probé la solución propuesta aquí React/JSX nombres de componentes dinámicos
Eso me dio un error al compilar (usando browserify para tragar). Esperaba XML donde estaba usando una sintaxis de matriz.
Podría resolver esto creando un método para cada componente:
newExampleComponent() { return <ExampleComponent />; } newComponent(type) { return this["new" + type + "Component"](); }Pero eso significaría un nuevo método para cada componente que creo. Debe haber una solución más elegante a este problema.
Estoy muy abierto a sugerencias.
<MyComponent /> se compila en React.createElement(MyComponent, {}) , que espera una cadena (etiqueta HTML) o una función (ReactClass) como primer parámetro.
Simplemente podría almacenar su clase de componente en una variable con un nombre que comience con una letra mayúscula. Consulte etiquetas HTML frente a componentes React .
var MyComponent = Components[type + "Component"]; return <MyComponent />;compila a
var MyComponent = Components[type + "Component"]; return React.createElement(MyComponent, {});Hay una documentación oficial sobre cómo manejar tales situaciones disponible aquí: https://facebook.github.io/react/docs/jsx-in-depth.html#choosing-the-type-at-runtime
Básicamente dice:
Equivocado:
import React from 'react'; import { PhotoStory, VideoStory } from './stories'; const components = { photo: PhotoStory, video: VideoStory }; function Story(props) { // Wrong! JSX type can't be an expression. return <components[props.storyType] story={props.story} />; }Correcto:
import React from 'react'; import { PhotoStory, VideoStory } from './stories'; const components = { photo: PhotoStory, video: VideoStory }; function Story(props) { // Correct! JSX type can be a capitalized variable. const SpecificStory = components[props.storyType]; return <SpecificStory story={props.story} />; }Debe haber un contenedor que asigne los nombres de los componentes a todos los componentes que se supone que deben usarse dinámicamente. Las clases de componentes deben registrarse en un contenedor porque, de lo contrario, en un entorno modular no hay un lugar único donde se pueda acceder a ellas. Las clases de componentes no se pueden identificar por sus nombres sin especificarlos explícitamente porque el name de la función se minimiza en producción.
Puede ser un objeto simple:
class Foo extends React.Component { ... } ... const componentsMap = { Foo, Bar }; ... const componentName = 'Fo' + 'o'; const DynamicComponent = componentsMap[componentName]; <DynamicComponent/>; O instancia de Map :
const componentsMap = new Map([[Foo, Foo], [Bar, Bar]]); ... const DynamicComponent = componentsMap.get(componentName);El objeto simple es más adecuado porque se beneficia de la propiedad abreviada.
Un módulo de barril con exportaciones con nombre puede actuar como tal mapa:
// 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/>;Esto funciona bien con una clase por estilo de código de módulo.
Los decoradores se pueden usar con componentes de clase para azúcar sintáctico, esto aún requiere especificar nombres de clase explícitamente y registrarlos en un mapa:
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 decorador se puede utilizar como componente de orden superior con componentes funcionales:
const Bar = props => ...; Bar.displayName = 'Bar'; export default dynamic(Bar); El uso de displayName no estándar en lugar de propiedades aleatorias también beneficia la depuración.