IT이야기

반응 / JSX 동적 구성 요소 이름

cyworld 2022. 3. 5. 23:10
반응형

반응 / 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

반응형