46 votes

Edition d'une structure de données riche dans React.js

Je suis en train de créer un simple basé sur une grille de l'éditeur pour une structure de données et je vais avoir quelques problèmes conceptuels React.js. Leur documentation n'est pas très utile, donc je suis en espérant que quelqu'un ici peut vous aider.

Tout d'abord, quelle est la bonne façon de transférer de l'état d'un composant externe à l'intérieure d'un composant? Est-il possible d'avoir les modifications de l'état dans l'intérieur de la composante "bulle" à l'extérieur du composant(s)?

Deuxièmement, les deux composantes distinctes de partager des données, de sorte qu'une mutation dans l'un est visible dans l'autre?

Ci-dessous est un exemple simplifié de la sorte de chose que je veux faire (JSFiddle version):

J'ai un company objet contenant un tableau de employee objets. Je veux poser le employee liste modifiable dans un réseau. Quand je clique sur le bouton, je veux voir le résultant company de l'objet, ainsi que toutes les mutations (écrit sur la console).

/** @jsx React.DOM */

var Cell = React.createClass({
    getInitialState: function () {
        return {data: ""};
    },

    componentWillMount: function () {
        this.setState({data: this.props.data});
    },
    onChange: function (evt) {
        console.log(this.state, evt.target.value);
        this.setState({data: evt.target.value});
    },
    render: function () {
        var data = this.props.data;
        return <input value={this.state.data} onChange={this.onChange} />
    }
});

var Row = React.createClass({
    render: function () {
        return (<div className="row">
            <Cell data={this.props.data.name} />
            <Cell data={this.props.data.location} />
            <Cell data={this.props.data.phone} />
        </div>);
    }
});

var Grid = React.createClass({
    render: function () {
        var rows = this.props.data.map(function (rowData, index) {
            return <Row key={index} data={rowData}>Row</Row>;
        });
        return <div className="table">{rows}</div>;
    }
});

var Button = React.createClass({
    getInitialState: function () {
        return {data: {}}
    },
    componentWillMount: function () {
        this.setState({data: this.props.data});
    },
    onClick: function () {
        console.log(this.state);
    },
    render: function () {
        return <button onClick={this.onClick}>Update</button>;
    }
});

var company = {
    name: "Innotech",
    employees: [
        {id: "1", name: "Peter", location: "IT", phone: "555-1212"},
        {id: "2", name: "Samir", location: "IT", phone: "555-1213"},
        {id: "3", name: "Milton", location: "loading dock", phone: "none"}
    ]
};


React.renderComponent(
    <div><Grid data={company.employees} /><Button data={company} /></div>,       
    document.getElementById('employees')
);

52voto

Ben Alpert Points 30381

Je pense que c'est le plus sous-documenté le cadre de Réagir dès maintenant. L'approche proposée pour la communication entre les composants est d'établir simplement des accessoires lors de la communication du parent à l'enfant de passer des rappels à travers des accessoires lors de la communication d'un enfant à un parent.

Quand vous sentez que vous souhaitez partager des données entre frère composants, cela signifie qu'il doit y avoir un composant parent la gestion de l'état et de son passage à deux composants. La plupart du temps, votre état devrait vivre près du haut de votre hiérarchie des composants, et chaque morceau de l'info devrait vivre (au plus) un état du composant, ce n'est plus.

Pour un peu plus à ce sujet, voir Pete Chasse du blog, la Pensée de Réagir.


Avec cela à l'esprit, j'ai mis à jour votre violon:

http://jsfiddle.net/spicyj/M6h22/

J'ai changé d' Grid , afin de ne pas maintenir son propre état, mais plutôt toujours affiche les données transmises par le biais de ses accessoires, et des appels onCellChange de ses accessoires quand il veut demander un changement des données à partir de son parent. (L' Grid composant s'attend à ce que ses parent pour mettre à jour la grille de l' data prop avec les données modifiées. Si le parent refuse (peut-être à cause de l'échec de la validation des données ou similaire), vous vous retrouvez avec une grille en lecture seule.)

Vous remarquerez également que j'ai créé un nouveau Editor composant pour envelopper la grille et son frère bouton. L' Editor composant essentiellement gère la totalité de la page. Dans une application réelle, il est probable que le contenu de la grille serait nécessaire d'ailleurs, et donc l'état serait déplacé plus. J'ai supprimé votre Button composant car il ne faisait pas beaucoup au-delà de la native <button> balise; j'ai quitté Cell , mais il pourrait être supprimé -- Row pourrait facilement utiliser <input> tags directement.

Espérons que cela a du sens. N'hésitez pas à demander si quelque chose n'est pas clair. Il sont généralement aussi les gens autour de la #reactjs salon IRC si vous voulez discuter plus à propos de tout cela.

7voto

Bernardo Points 522

J'ai été d'explorer ReactJS pour la dernière semaine ou deux. Ma contribution à votre question, c'est poser une nouvelle question: pourquoi voulez-vous séparer les composants Cellulaires à partir de la Ligne et des composantes de la Grille?

Venant d'une Dorsale en arrière-plan, la Cellule & Ligne & Grille de sens, afin de contrôler avec précision chaque Cellule de la colonne vertébrale.Les vues. Cependant, il semble qu'un contrôle granulaire & DOM mise à jour est ce qui ReactJS essaie de le résoudre pour vous, qui me parle pour avoir une Grille de composant qui implémente une Ligne/Cellule à l'intérieur d'elle-même:

var Grid = React.createClass({
    onChange: function(evt, field) {
        this.props.data[field] = evt.target.value;
    },

    render: function () {
        var rows = this.state.data.map(function (rowData, index) {
            return (
                <div className="row" key={index}>
                    <input value={rowData.name} onChange={this.onChange.bind(null, "name")} />
                    <input value={rowData.location} onChange={this.onChange.bind(null, "location")} />
                    <input value={rowData.phone} onChange={this.onChange.bind(null, "phone")} />
                </div>
            );
        });

        return <div className="table">
                   {rows}
               </div>;
    }
});

(Ignorer la sur*la manipulation du Changement, la place pour amélioration. Code non testé)

La question est: serait-il possible de ré-utiliser la Cellule ou la Ligne en tant que composants individuels d'ailleurs? Pour moi la réponse est "très probablement". Auquel cas ma solution ci-dessus a de sens, à mon humble avis, et de se débarrasser du problème de la transmission des données et des changements up & down.

0voto

DjebbZ Points 535

Une autre façon de partager des données entre frère composants lorsqu'un composant parent n'a pas de sens est l'utilisation d'événements entre les composants. Par exemple, vous pouvez utiliser la colonne vertébrale.Événements, Node.js Émetteur porté sur le navigateur, ou de toute autre lib. Vous pouvez même utiliser Bacon.js si vous préférez réactif ruisseaux. Il y a un grand exemple simple de combiner Bacon.js et React.js ici : http://joshbassett.info/2014/reactive-uis-with-react-and-bacon/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X