리액트 - 컴포넌트 동적 Import
사용자 입력에 따라 다른 컴포넌트를 렌더링하는 페이지가 있습니다.현재 아래와 같이 각 컴포넌트의 Import를 하드코딩하고 있습니다.
import React, { Component } from 'react'
import Component1 from './Component1'
import Component2 from './Component2'
import Component3 from './Component3'
class Main extends Component {
render() {
var components = {
'Component1': Component1,
'Component2': Component2,
'Component3': Component3
};
var type = 'Component1'; // just an example
var MyComponent = Components[type];
return <MyComponent />
}
}
export default Main
하지만 저는 항상 컴포넌트를 변경/추가합니다.컴포넌트의 이름과 경로만 저장하고 이들을 다른 파일로 동적으로 Import하는 방법이 있습니까?
내가 달성하려고 했던 것에 대해 약간의 혼란이 있었을지도 모른다고 생각한다.문제가 해결되었고, 아래에 해결 방법을 나타내는 코드를 보여드렸습니다.
개별 파일(컴포넌트)Index.js):
let Components = {};
Components['Component1'] = require('./Component1').default;
Components['Component2'] = require('./Component2').default;
Components['Component3'] = require('./Component3').default;
export default Components
메인 파일(Main.js):
import React, { Component } from 'react';
import Components from './ComponentIndex';
class Main extends Component {
render () {
var type = 'Component1'; // example variable - will change from user input
const ComponentToRender = Components[type];
return <ComponentToRender/>
}
}
export default Main
이 방법을 사용하면 Import가 한 파일에 있고 한 번에 한 줄만 변경하면 되기 때문에 컴포넌트를 빠르게 추가하거나 제거할 수 있습니다.
질문이 너무 오래됐기 때문에 정답은 아마 괜찮았을 거예요.그러나 현재 같은 문제가 있는 경우 필요한 컴포넌트만 로드하고 다른 컴포넌트는 모두 로드하지 않도록 동적 Import를 사용해야 합니다.
const component = React.lazy(() => import('./component.jsx'));
여기서 예를 시험해 보세요: 데모
import React, { Component } from 'react'
import Component1 from './Component1'
import Component2 from './Component2'
import Component3 from './Component3'
class Main extends Component {
render() {
var type = 'Component1'; // just an example
return (
<div>
{type == "Component1" && <Component1 />}
{type == "Component2" && <Component2 />}
...
</div>
)
}
}
export default Main
설치된 조건부 렌더링을 사용할 수 있습니다.도움이 되었으면 좋겠다
다음은 또 다른 해결 방법입니다.필요한 컴포넌트 리스트가 표시됩니다.list = ['c1', 'c2', 'c3']
. json 파일에서 배열로 풀 수 있습니다(redex-store를 사용하여 this.props.getForms()로 폼을 가져옵니다).단, 컴포넌트 목록을 수동으로 생성하여 액세스할 수 있습니다.
componentDidMount = () => {
//we get elements list from any source to redux-store
this.props.getForms();
//access redux-store to the list
const forms = this.props.configBody.sets;
//make deep object copy
const updatedState = { ...this.state };
updatedState.modules = [];
if (forms) {
//here is the very dynamic import magic: we map the import list and prepare to store the imports in Component`s state
const importPromises = forms.map(p =>
import(`../TemplateOrders/Template${p.order}`)
.then(module => {
updatedState.modules.push(module.default)
})
.catch(errorHandler(p))
)
//wait till all imports are getting resolved
Promise.all(importPromises)
.then(res =>
//then run setState
this.setState({ ...updatedState }, () => {
console.log(this.state);
}))
}
}
render() {
const forms = this.props.configBody.sets;
//we iterate through the modules and React.createElemet`s
const list = this.state.modules
? this.state.modules.map((e, i) =>
createElement(e, { key: forms[i].title }, null)
)
: [];
return (
<Fragment>
<Link to='/'>Home</Link>
<h1>hello there</h1>
//push them all to get rendered as Components
{list.map(e => e)}
</Fragment>
)
}
따라서 앱이 로드되면 필요한 모듈을 가져옵니다.
약속을 사용하여 Import하려고 했는데 모듈은 이미 약속입니다.
최근에 서버에서 아약스할 필요가 있는 경우에는 모듈을 분할한 후 require(또는 그와 비슷한 것)로 번들해야 합니다.
구성 요소를 마이크로 앱으로 번들하고 URL에서 애플리케이션에 핫 로드할 수 있습니다.사이트 레벨의 설정에 근거해 루트로부터의 컴포넌트 및 마이크로 앱의 동적 Import를 서포트하는 POC를 다음에 나타냅니다.
https://github.com/eschall/react-micro-frontend
약속 없이 동적 Import를 수행할 수 있는 또 하나의 방법:
import React from "react";
import ColumnSet1Brick from "./sets/column-set/column-set-1-brick";
import ColumnSet2Brick from "./sets/column-set/column-set-2-brick";
import ColumnSet3Brick from "./sets/column-set/column-set-3-brick";
import ColumnSet4Brick from "./sets/column-set/column-set-4-brick";
const setClasses = {
ColumnSet1Brick,
ColumnSet2Brick,
ColumnSet3Brick,
ColumnSet4Brick
};
export default class SetBrickStack extends React.Component {
...
getColumnSetInstance = (n) => new (setClasses[`ColumnSet${n}Brick`])(this.paramFactory.getBasicProps());
getBricksOnInit = () => {
const columnSets = [1, 2, 3, 4];
const bricksParams = columnSets.map(this.getColumnSetInstance);
return bricksParams;
};
}
비결은 babel이 클래스를 react__와 같은 다른 이름으로 컴파일하는 것입니다.WEBPACK_IPORTED_MODULE_1__기본값으로 접근하려면 컴파일 모듈 이름을 하나의 객체에 할당해야 합니다.그러므로 참조를 사용하여 객체를 컴파일하는 setClasses가 존재합니다.
const setClasses = {
ColumnSet1Brick: react__WEBPACK_IMPORTED_MODULE_1___default,
ColumnSet2Brick: react__WEBPACK_IMPORTED_MODULE_2___default,
ColumnSet3Brick: react__WEBPACK_IMPORTED_MODULE_3___default,
ColumnSet4Brick: react__WEBPACK_IMPORTED_MODULE_4___default
};
통상적인 클래스명으로 Import 할 수 있습니다.
new (setClasses[`ColumnSet${n}Brick`])(parameters)
React.createElement를 사용하는 컴포넌트 빌드 함수를 작성할 수 있습니다.이렇게 하면 도우미 파일에서 함수를 가져올 수 있습니다.이 예에서는 상세 정보가 없으면 더 많은 코드를 표시하기가 어렵지만 이 컴포넌트에서 논리를 완전히 삭제하는 것이 목적인 경우 이 파일에서 상태 도우미를 사용할 수도 있습니다.
class Main extends Component {
constructor(props) {
super();
this.state = { displayComponent: Component1 }
}
buildComponent = () => {
// create element takes additional params for props and children
return React.createElement( this.state.displayComponent )
}
render() {
var type = 'Component1'; // just an example
return (
<div>
{ this.buildComponent() }
</div>
)
}
}
동적 Import를 사용해야 하는 경우 필요한 컴포넌트만 로드하고 다른 컴포넌트는 모두 로드하지 않도록 합니다.코드 검색 사용
(async () => {
const { Component1 } = await import('./Component1');
})();
'react-router-dom'에서 Route 및 Switch를 사용하여 경로를 기반으로 구성 요소를 동적으로 렌더링할 수 있습니다.여기 샘플이 있습니다.
render() {
return (
<>
<Header />
<BrowserRouter>
<Switch>
<Route path="/abc" exact render={() => (<Abc />)}/>
<Route path="/abcd" exact render={() => (<Abcd {...this.props} />)}/>
<Route path="/xyz" exact render={() => (<Xyz />)}/>
</Switch>
</BrowserRouter>
<Footer /></>
); }
언급URL : https://stackoverflow.com/questions/48268507/react-dynamically-import-components
'code' 카테고리의 다른 글
jq를 사용하여 json 문서의 단일 값을 업데이트하려면 어떻게 해야 합니까? (0) | 2023.03.19 |
---|---|
TypeScript에서 "keyof typeof"는 무엇을 의미합니까? (0) | 2023.03.19 |
MVC 4에서의 적절한 JSON 시리얼화 (0) | 2023.03.19 |
적절한 JavaScript 문자열 이스케이프를 사용하여 XSS가 JSON 응답을 악용할 수 있습니까? (0) | 2023.03.19 |
다중 인수 대 옵션 개체 (0) | 2023.03.19 |