반응 / JSX 동적 구성 요소 이름
나는 그 종류에 따라 동적으로 컴포넌트를 렌더링하려고 한다.
예를 들면 다음과 같다.
var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />;
// Returns <examplecomponent /> instead of <ExampleComponent />
여기에 제안된 Resact/JSX 동적 구성 요소 이름을 사용해 보았다.
그것은 컴파일할 때 실수를 했다.그것은 내가 배열 구문을 사용하는 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);
무작위 속성 대신 비표준을 사용하는 것도 디버깅에 유리하다.
새로운 해결책을 찾아냈다.참고로 나는 ES6 모듈을 사용하고 있으므로 수업을 요청한다.대신 새 리액트 클래스를 정의할 수도 있다.
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/>
}
React.lazy의 도입으로 우리는 이제 진정한 동적 접근법을 사용하여 구성요소를 가져와 렌더링할 수 있다.
import React, { lazy, Suspense } from 'react';
const App = ({ componentName, ...props }) => {
const DynamicComponent = lazy(() => import(`./${componentName}`));
return (
<Suspense fallback={<div>Loading...</div>}>
<DynamicComponent {...props} />
</Suspense>
);
};
이 접근방식은 물론 파일 계층에 대해 몇 가지 가정을 하고 코드를 쉽게 해독할 수 있다.
지도가 있는 것은 많은 양의 구성 요소들로 볼 때 전혀 좋아 보이지 않는다.나는 사실 아무도 이런 것을 제안하지 않았다는 것이 놀랍다.
var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule);
이것은 내가 json 배열의 형태로 적재된 꽤 많은 양의 구성품을 렌더링해야 할 때 정말 도움이 되었다.
예를 들어,flag
, 그리고 다를 바 없다.state
또는props
:
import ComponentOne from './ComponentOne';
import ComponentTwo from './ComponentTwo';
~~~
const Compo = flag ? ComponentOne : ComponentTwo;
~~~
<Compo someProp={someValue} />
깃발 포함Compo
중 하나로 채우다ComponentOne
또는ComponentTwo
그리고 그 다음Compo
반응 구성요소처럼 행동할 수 있다.
동적 구성 요소 로딩으로 다양한 뷰에 액세스하고자 하는 일시 중단.다음 코드는 url의 검색 문자열에서 구문 분석된 문자열을 사용하여 이를 수행하는 방법에 대한 작업 예를 제공한다.
다음 URL 경로를 사용하여 두 개의 고유한 보기가 있는 '스노즈베리' 페이지에 액세스하고 싶다고 가정해 봅시다.
'http://localhost:3000/snozberrys?aComponent'
그리고
'http://localhost:3000/snozberrys?bComponent'
View의 컨트롤러를 다음과 같이 정의한다.
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'));
이와 같은 구성 요소에서 *를 내보낼 수 있다고 가정하면...
// src/components/index.js
export * from './Home'
export * from './Settings'
export * from './SiteList'
그런 다음 *를 새 컴프 개체로 다시 가져오면 모듈 액세스에 사용할 수 있다.
// src/components/DynamicLoader.js
import React from 'react'
import * as comps from 'components'
export default function ({component, defaultProps}) {
const DynamicComponent = comps[component]
return <DynamicComponent {...defaultProps} />
}
그릴 구성 요소를 식별하는 문자열 값을 도색해야 하는 위치에 전달하십시오.
<DynamicLoader component='Home' defaultProps={someProps} />
우리는 항상 우리의 실제 구성 요소를 알고 있기 때문에 스위치 케이스를 적용하려고 생각했기 때문에 나는 약간 다른 접근 방식을 사용했다.또한 나의 경우 구성품의 총수가 약 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} />
}
}
편집: 다른 답변이 더 낫습니다, 주석을 참조하십시오.
나는 같은 문제를 이렇게 해결했다.
...
render : function () {
var componentToRender = 'component1Name';
var componentLookup = {
component1Name : (<Component1 />),
component2Name : (<Component2 />),
...
};
return (<div>
{componentLookup[componentToRender]}
</div>);
}
...
참조URL: https://stackoverflow.com/questions/29875869/react-jsx-dynamic-component-name
'IT이야기' 카테고리의 다른 글
재조정 변수를 반응시키다. 정의되지 않은 상태로 반환하다. (0) | 2022.03.06 |
---|---|
부에루터 이름 및 매개 변수로 경로 가져오기 (0) | 2022.03.06 |
어떤 상황에서 "필수" 구문보다 v-text를 선택하겠는가? (0) | 2022.03.05 |
next.js + 리액션 이전 페이지로 돌아가기 (0) | 2022.03.05 |
키보드 수신기를 on 핸들러에 추가하는 방법클릭? (0) | 2022.03.05 |