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.

96
demandé sur Community 2015-04-26 12:23:59

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, {});
107
répondu Alexandre Kirszenberg 2015-04-26 10:07:10

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} />;
}
80
répondu gmfvpereira 2016-11-30 19:06:35

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" });
}
10
répondu Sam 2015-04-26 09:58:27

Si vos composants sont globaux, vous pouvez simplement faire:

var nameOfComponent = "SomeComponent";
React.createElement(window[nameOfComponent], {});
6
répondu Ray 2015-11-20 20:17:02

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 })
    )
  }
}
2
répondu Ricardo Pedroni 2016-08-19 18:27:04

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} />

    }
  }
0
répondu abhirathore2006 2016-05-31 18:51:25

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'));
0
répondu 1-14x0r 2017-10-03 04:41:59

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>);
}
...
-1
répondu Hammad Akhwand 2017-04-14 19:01:15