Nom du composant dynamique React / JSX
j'essaie de rendre dynamiquement les composants en fonction de leur type.
par exemple:
var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />;
// Returns <examplecomponent /> instead of <ExampleComponent />
j'ai essayé la solution proposée ici React / JSX noms des composants dynamiques
qui m'a donné une erreur lors de la compilation (en utilisant browserify pour gulfp). Il attendait XML où j'utilisais une syntaxe de tableau.
je pourrais résoudre ceci en créant une méthode pour chaque composant:
newExampleComponent() {
return <ExampleComponent />;
}
newComponent(type) {
return this["new" + type + "Component"]();
}
Mais cela signifierait une nouvelle méthode pour chaque composant que je crée. Il doit y avoir une solution plus élégante à ce problème.
je suis très ouvert aux suggestions.
8 réponses
<MyComponent />
compile React.createElement(MyComponent, {})
, qui attend une chaîne de caractères (balise HTML) ou une fonction (ReactClass) comme premier paramètre.
vous pouvez simplement stocker votre classe de composants dans une variable avec un nom qui commence par une lettre majuscule. Voir balises HTML vs React Components .
var MyComponent = Components[type + "Component"];
return <MyComponent />;
compile
var MyComponent = Components[type + "Component"];
return React.createElement(MyComponent, {});
Il ya une documentation officielle sur la façon de gérer de telles situations est disponible ici: https://facebook.github.io/react/docs/jsx-in-depth.html#choosing-the-type-at-runtime
en gros, ça dit:
Mauvais:
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} />;
}
Correct:
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} />;
}
j'ai trouvé une nouvelle solution. Notez que j'utilise des modules ES6, donc j'ai besoin de la classe. Vous pouvez également définir une nouvelle classe React à la place.
var components = {
example: React.createFactory( require('./ExampleComponent') )
};
var type = "example";
newComponent() {
return components[type]({ attribute: "value" });
}
Si vos composants sont globaux, vous pouvez simplement faire:
var nameOfComponent = "SomeComponent";
React.createElement(window[nameOfComponent], {});
pour un composant d'enrubannage, une solution simple serait d'utiliser React.createElement
directement (en utilisant ES6).
import RaisedButton from 'mui/RaisedButton'
import FlatButton from 'mui/FlatButton'
import IconButton from 'mui/IconButton'
class Button extends React.Component {
render() {
const { type, ...props } = this.props
let button = null
switch (type) {
case 'flat': button = FlatButton
break
case 'icon': button = IconButton
break
default: button = RaisedButton
break
}
return (
React.createElement(button, { ...props, disableTouchRipple: true, disableFocusRipple: true })
)
}
}
j'ai utilisé une approche un peu différente, comme nous savons toujours nos composants réels, donc j'ai pensé à appliquer cas de commutation. De plus, le nombre total de composantes était d'environ 7 à 8 dans mon cas.
getSubComponent(name) {
let customProps = {
"prop1" :"",
"prop2":"",
"prop3":"",
"prop4":""
}
switch (name) {
case "Component1": return <Component1 {...this.props} {...customProps} />
case "Component2": return <Component2 {...this.props} {...customProps} />
case "component3": return <component3 {...this.props} {...customProps} />
}
}
Suspension nous souhaitons accéder à différentes vues avec chargement dynamique des composants.Le code suivant donne un exemple pratique de la façon d'accomplir ceci en utilisant une chaîne parée à partir de la chaîne de recherche d'une url.
permet de supposer que nous voulons accéder à une page 'snozberrys' avec deux vues uniques en utilisant ces chemins url:
'http://localhost:3000/snozberrys?aComponent'
et
'http://localhost:3000/snozberrys?bComponent'
nous définissons le contrôleur de notre vue comme ceci:
import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import {
BrowserRouter as Router,
Route
} from 'react-router-dom'
import AComponent from './AComponent.js';
import CoBComponent sole from './BComponent.js';
const views = {
aComponent: <AComponent />,
console: <BComponent />
}
const View = (props) => {
let name = props.location.search.substr(1);
let view = views[name];
if(view == null) throw "View '" + name + "' is undefined";
return view;
}
class ViewManager extends Component {
render() {
return (
<Router>
<div>
<Route path='/' component={View}/>
</div>
</Router>
);
}
}
export default ViewManager
ReactDOM.render(<ViewManager />, document.getElementById('root'));
Edit: les autres réponses sont meilleures, voir les commentaires.
j'ai résolu le même problème de cette façon:
...
render : function () {
var componentToRender = 'component1Name';
var componentLookup = {
component1Name : (<Component1 />),
component2Name : (<Component2 />),
...
};
return (<div>
{componentLookup[componentToRender]}
</div>);
}
...