web-dev-qa-db-fra.com

Ajouter dynamiquement des composants enfants dans React

Mon objectif est d'ajouter des composants de manière dynamique sur un composant page/parent.

J'ai commencé avec un exemple de modèle de base comme ceci:

main.js:

var App = require('./App.js');
var SampleComponent = require('./SampleComponent.js');
ReactDOM.render(<App/>, document.body);
ReactDOM.render(<SampleComponent name="SomeName"/>, document.getElementById('myId'));

App.js:

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                <div id="myId">myId div</div>
            </div>

        );
    }

});

SampleComponent.js:

var SampleComponent = React.createClass({
    render: function() {
        return (
            <div>
                <h1>Sample Component! </h1>
            </div>
        );
    }
});

Ici, SampleComponent est monté sur le noeud <div id="myId"></div>, qui est pré-écrit dans le modèle App.js. Mais que se passe-t-il si je dois ajouter un nombre indéterminé de composants à un composant App? Évidemment, je ne peux pas avoir tout le nécessaire divs assis là.

Après avoir lu certains tutoriels, je ne comprends toujours pas comment les composants sont créés et ajoutés dynamiquement au composant parent. Quel est un moyen de le faire?

61
Justin Trevein

Vous devez transmettre vos composants en tant qu'enfants, comme ceci:

var App = require('./App.js');
var SampleComponent = require('./SampleComponent.js');
ReactDOM.render(
    <App>
        <SampleComponent name="SomeName"/> 
    <App>, 
    document.body
);

Et ensuite, ajoutez-les dans le corps du composant:

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                {
                    this.props.children
                }
            </div>
        );
    }
});

Vous n'avez pas besoin de manipuler manuellement le code HTML, React le fera pour vous. Si vous souhaitez ajouter des composants enfants, il vous suffit de modifier les accessoires ou de préciser que cela dépend. Par exemple:

var App = React.createClass({

    getInitialState: function(){
        return [
            {id:1,name:"Some Name"}
        ]
    },

    addChild: function() {
        // State change will cause component re-render
        this.setState(this.state.concat([
            {id:2,name:"Another Name"}
        ]))
    }

    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                <button onClick={this.addChild}>Add component</button>
                {
                    this.state.map((item) => (
                        <SampleComponent key={item.id} name={item.name}/>
                    ))
                }
            </div>
        );
    }

});
51
Nikolai Mavrenkov

Tout d'abord, je n'utiliserais pas document.body . Ajoutez plutôt un conteneur vide:

index.html:

<html>
    <head></head>
    <body>
        <div id="app"></div>
    </body>
</html>

Puis choisissez de ne rendre que votre élément <App />:

main.js:

var App = require('./App.js');
ReactDOM.render(<App />, document.getElementById('app'));

Dans App.js, vous pouvez importer vos autres composants et ignorer complètement votre code de rendu DOM:

App.js:

var SampleComponent = require('./SampleComponent.js');

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component!</h1>
                <SampleComponent name="SomeName" />
            </div>
        );
    }
});

SampleComponent.js:

var SampleComponent = React.createClass({
    render: function() {
        return (
            <div>
                <h1>Sample Component!</h1>
            </div>
        );
    }
});

Vous pouvez ensuite interagir par programmation avec un nombre quelconque de composants en les important dans les fichiers de composants nécessaires à l'aide de require.

5
Chris

Partage ma solution ici, basée sur la réponse de Chris. J'espère que cela peut aider les autres.

J'avais besoin d'ajouter dynamiquement des éléments enfants dans ma JSX, mais d'une manière plus simple que les contrôles conditionnels dans ma déclaration de retour. Je souhaite montrer un chargeur si les éléments enfants ne sont pas encore prêts. C'est ici:

export class Settings extends React.PureComponent {
  render() {
    const loading = (<div>I'm Loading</div>);
    let content = [];
    let pushMessages = null;
    let emailMessages = null;

    if (this.props.pushPreferences) {
       pushMessages = (<div>Push Content Here</div>);
    }
    if (this.props.emailPreferences) {
      emailMessages = (<div>Email Content Here</div>);
    }

    // Push the components in the order I want
    if (emailMessages) content.Push(emailMessages);
    if (pushMessages) content.Push(pushMessages);

    return (
      <div>
        {content.length ? content : loading}
      </div>
    )
}

Maintenant, je réalise que je pourrais aussi simplement mettre {pushMessages} et {emailMessages} directement dans mon return() ci-dessous, mais en supposant que mon contenu soit encore plus conditionnel, mon return() semblerait simplement encombré.

3
user888750

Tout d'abord un avertissement: vous ne devriez jamais bricoler avec le DOM géré par React, ce que vous faites en appelant ReactDOM.render(<SampleComponent ... />);

Avec React, vous devez utiliser SampleComponent directement dans l'application principale.

var App = require('./App.js');
var SampleComponent = require('./SampleComponent.js');
ReactDOM.render(<App/>, document.body);

Le contenu de votre composant n'est pas pertinent, mais il devrait être utilisé comme ceci:

var App = React.createClass({
    render: function() {
        return (
            <div>
                <h1>App main component! </h1>
                <SampleComponent name="SomeName"/>
            </div>
        );
    }
});

Vous pouvez ensuite étendre votre composant d'application pour utiliser une liste.

var App = React.createClass({
    render: function() {
        var componentList = [
            <SampleComponent name="SomeName1"/>,
            <SampleComponent name="SomeName2"/>
        ]; // Change this to get the list from props or state
        return (
            <div>
                <h1>App main component! </h1>
                {componentList}
            </div>
        );
    }
});

Je vous conseillerais vraiment de consulter la documentation React, puis de suivre les instructions de "Procédure de démarrage". Le temps que vous passerez à cela sera rentable plus tard.

https://facebook.github.io/react/index.html

2
Neil Twist