it-swarm.com.de

Reagieren - Komponenten dynamisch importieren

Ich habe eine Seite, die verschiedene Komponenten basierend auf Benutzereingaben darstellt. Im Moment habe ich die Importe für jede Komponente wie folgt fest codiert:

    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

Ich verändere/füge jedoch ständig Komponenten hinzu. Gibt es eine Möglichkeit, eine Datei zu haben, die NUR die Namen und Pfade der Komponenten speichert und diese dann dynamisch in eine andere Datei importiert werden?

10
LEJ

Ich glaube, es gab einige Verwirrung darüber, was ich erreichen wollte. Ich konnte das Problem lösen, das ich hatte, und habe unten meinen Code gezeigt, der zeigt, wie ich es gelöst habe.

Separate Datei (ComponentIndex.js):

    let Components = {};

    Components['Component1'] = require('./Component1').default;
    Components['Component2'] = require('./Component2').default;
    Components['Component3'] = require('./Component3').default;

    export default Components

Hauptdatei (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

Mit dieser Methode kann ich sehr schnell Komponenten hinzufügen/entfernen, da die Importe in einer Datei sind und nur jeweils eine Zeile geändert werden muss.

10
LEJ

Sie können Ihre Komponenten als Mikro-Apps bündeln und über eine URL im laufenden Betrieb in Ihre Anwendung laden. Hier ist ein POC, der das dynamische Importieren von Komponenten und Mikro-Apps von einer Route basierend auf einer Konfiguration auf Site-Ebene unterstützt.

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

1
Eric Schall

sie könnten eine Komponentenerstellungsfunktion erstellen, die React.createElement verwendet. Auf diese Weise können Sie die Funktion aus einer Hilfsdatei importieren. In diesem Beispiel ist es schwierig, mehr Code ohne weitere Informationen anzuzeigen. Sie können jedoch auch Statushilfen aus dieser Datei verwenden, wenn Sie die Logik vollständig aus dieser Komponente entfernen möchten.

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>
    )
}

}

0
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

Sie können das bedingte Rendering insted verwenden. Ich hoffe es wird helfen

Überprüfen Sie dies

0
user8685433

Hier ist eine andere Lösung: Wir erhalten die Liste der benötigten Komponenten list = ['c1', 'c2', 'c3']. Es kann von der JSON-Datei in ein Array gezogen werden (ich verwende Redux-Store, damit ich das Abrufen von Formularen durch this.props.getForms () initiiere). Sie können die Liste der Komponenten jedoch nur manuell erstellen und aufrufen.

    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>
        )
    }

Wenn Ihre App geladen ist, werden die erforderlichen Module abgerufen.

Ich dachte, ich verwende Versprechen , um sie zu importieren, aber Module sind bereits Versprechen.

Für den Fall, dass wir sie in letzter Zeit vom Server entfernen müssen, müssen wir die Module aufteilen, bevor wir sie mit require (oder so ähnlich) bündeln.

0
AlexNikonov