Имя динамического компонента React / JSX
Я пытаюсь динамически отображать компоненты на основе их типа.
например:
var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />;
// Returns <examplecomponent /> instead of <ExampleComponent />
я попробовал решение, предложенное здесь имена динамических компонентов React/JSX
это дало мне ошибку при компиляции (с помощью browserify для gulp). Он ожидал XML, где я использовал синтаксис массива.
я мог бы решить эту проблему, создав метод для каждого компонента:
newExampleComponent() {
return <ExampleComponent />;
}
newComponent(type) {
return this["new" + type + "Component"]();
}
но это будет означать новый способ каждый компонент, который я создаю. Должно быть более элегантное решение этой проблемы.
Я очень открыт для предложений.
8 ответов:
<MyComponent />
компилируется вReact.createElement(MyComponent, {})
, который ожидает строку (HTML-тег) или функцию (ReactClass) в качестве первого параметра.вы можете просто сохранить свой класс компонентов в переменной с именем, которое начинается с прописной буквы. Смотрите HTML теги vs React Components.
var MyComponent = Components[type + "Component"]; return <MyComponent />;
компилируется в
var MyComponent = Components[type + "Component"]; return React.createElement(MyComponent, {});
существует официальная документация о том, как справиться с такими ситуациями доступна здесь: https://facebook.github.io/react/docs/jsx-in-depth.html#choosing-the-type-at-runtime
в основном он говорит:
неправильно:
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} />; }
правильно:
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} />; }
Я придумал новое решение. Обратите внимание, что я использую модули ES6, поэтому мне требуется класс. Вместо этого можно также определить новый класс React.
var components = { example: React.createFactory( require('./ExampleComponent') ) }; var type = "example"; newComponent() { return components[type]({ attribute: "value" }); }
Если компоненты являются глобальными, Вы можете просто сделать:
var nameOfComponent = "SomeComponent"; React.createElement(window[nameOfComponent], {});
для компонента оболочки простым решением было бы просто использовать
React.createElement
непосредственно (с помощью 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 }) ) } }
я использовал немного другой подход, так как мы всегда знаем наши фактические компоненты, поэтому я решил применить случай переключения. Также нет деталей по 7-8 в моем случае.
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} /> } }
Suspose мы хотим получить доступ к различным представлениям с динамической загрузкой компонентов.В следующем коде приведен рабочий пример того, как это сделать с помощью строки, анализируемой из строки поиска url-адреса.
предположим, что мы хотим получить доступ к странице "snozberrys" с двумя уникальными представлениями, используя эти url-пути:
'http://localhost:3000/snozberrys?aComponent'
и
'http://localhost:3000/snozberrys?bComponent'
мы определяем контроллер нашего представления следующим образом:
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'));
изменить: другие ответы лучше, см. комментарии.
Я решил ту же проблему следующим образом:
... render : function () { var componentToRender = 'component1Name'; var componentLookup = { component1Name : (<Component1 />), component2Name : (<Component2 />), ... }; return (<div> {componentLookup[componentToRender]} </div>); } ...