유형에 따라 구성 요소를 동적으로 렌더링하려고합니다.
예를 들면 다음과 같습니다.
var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />;
// Returns <examplecomponent /> instead of <ExampleComponent />
여기에 제안 된 솔루션을 시도했습니다 .React / JSX 동적 구성 요소 이름
컴파일 할 때 오류가 발생했습니다 (gulp에 browserify 사용). 배열 구문을 사용하고있는 XML을 기대했습니다.
모든 구성 요소에 대한 방법을 만들어서 해결할 수 있습니다.
newExampleComponent() {
return <ExampleComponent />;
}
newComponent(type) {
return this["new" + type + "Component"]();
}
그러나 그것은 내가 만드는 모든 구성 요소에 대한 새로운 방법을 의미합니다. 이 문제에 대한보다 우아한 해결책이 있어야합니다.
나는 제안에 매우 개방적이다.
답변
<MyComponent />
로 컴파일 React.createElement(MyComponent, {})
하면 문자열 (HTML 태그) 또는 함수 (ReactClass)가 첫 번째 매개 변수로 필요합니다.
대문자로 시작하는 이름을 가진 변수에 컴포넌트 클래스를 저장할 수 있습니다. HTML 태그와 반응 구성 요소를 참조하십시오 .
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} />;
}
답변
컴포넌트 이름을 동적으로 사용해야하는 모든 컴포넌트에 맵핑하는 컨테이너가 있어야합니다. 구성 요소 클래스는 컨테이너 환경에 등록해야합니다. 모듈 식 환경에서는 액세스 할 수있는 단일 위치가 없기 때문입니다. name
프로덕션에서 기능 이 축소되었으므로 구성 요소 클래스를 명시 적으로 지정하지 않으면 이름으로 식별 할 수 없습니다 .
구성 요소 맵
일반 객체가 될 수 있습니다.
class Foo extends React.Component { ... }
...
const componentsMap = { Foo, Bar };
...
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;
또는 Map
인스턴스 :
const componentsMap = new Map([[Foo, Foo], [Bar, Bar]]);
...
const DynamicComponent = componentsMap.get(componentName);
일반 객체는 속성 속기의 이점이 있으므로 더 적합합니다.
배럴 모듈
배럴 모듈 라는 이름의 수출과는지도의 역할을 할 수 있습니다 :
// 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/>;
이것은 모듈 코드 스타일 당 하나의 클래스와 잘 작동합니다.
데코레이터
데코레이터는 구문 설탕의 클래스 구성 요소와 함께 사용할 수 있지만 클래스 이름을 명시 적으로 지정하고 맵에 등록해야합니다.
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'
...
}
데코레이터는 기능적 구성 요소를 사용하여 고차 구성 요소로 사용할 수 있습니다.
const Bar = props => ...;
Bar.displayName = 'Bar';
export default dynamic(Bar);
의 사용은 비표준displayName
대신 임의의 속성은 또한 디버깅 혜택을 제공합니다.
답변
새로운 해결책을 찾았습니다. 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 })
)
}
}
답변
구성 요소 맵이있는 모든 옵션에서 ES6 짧은 구문을 사용하여 맵을 정의하는 가장 간단한 방법을 찾지 못했습니다.
import React from 'react'
import { PhotoStory, VideoStory } from './stories'
const components = {
PhotoStory,
VideoStory,
}
function Story(props) {
//given that props.story contains 'PhotoStory' or 'VideoStory'
const SpecificStory = components[props.story]
return <SpecificStory/>
}