Подтвердить что ты не робот

Реагировать - динамически импортировать компоненты

У меня есть страница, которая отображает разные компоненты на основе ввода пользователем. На данный момент я жестко закодировал импорт для каждого компонента, как показано ниже:

    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

Тем не менее, я постоянно меняю/добавляю компоненты. Есть ли способ, возможно, иметь файл, в котором хранятся ТОЛЬКО имена и пути компонентов, и они затем динамически импортируются в другой файл?

4b9b3361

Ответ 1

Я думаю, что, возможно, была какая-то путаница в отношении того, чего я пытался достичь. Мне удалось решить вопрос, который у меня был, и я показал свой код ниже, который показывает, как я его решил.

Отдельный файл (ComponentIndex.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

Этот метод позволяет мне быстро добавлять/удалять компоненты, поскольку импорт находится в одном файле и требует изменения только одной строки за раз.

Ответ 2

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

Вы можете использовать условный рендеринг. Надеюсь, это поможет

Проверь это

Ответ 3

вы можете создать функцию построения компонента, которая использует 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>
    )
}

}

Ответ 4

Вот еще одно решение: мы получаем список необходимых компонентов list = ['c1', 'c2', 'c3']. Он может быть извлечен из файла json в массив (я использую redux-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 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 
        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>
        )
    }

Поэтому, когда ваше приложение загружено, оно извлекает нужные модули.

Я думал использовать обещания для их импорта, но модули уже являются обещаниями.

В случае, если в последнее время нам нужно будет переадресовать их с сервера, поэтому нам нужно разделить модули перед объединением с помощью require (или что-то в этом роде), который точно не знает.

Ответ 5

Вы можете связывать свои компоненты как микро-приложения и загружать их в свое приложение по ссылке. Вот документ, который поддерживает динамический импорт компонентов и микроприложений из маршрута на основе конфигурации на уровне сайта.

https://github.com/eschall/react-micro-frontend