web-dev-qa-db-fra.com

React + Flux - les données stockées doivent-elles être stockées dans un état de composant, ou accessoires?

Si le magasin de flux est un singleton qui maintient l'état des données, pourquoi les composants utilisent-ils setState et non setProps lorsqu'ils accèdent aux magasins? Cela ne signifierait-il pas simplement que j'ai commencé à enregistrer l'état de l'application à deux (ou plus) endroits?

La documentation Flux/React et les exemples semblent indiquer setState comme la solution préférée, mais j'ai eu une conversation intéressante avec quelques collègues de travail et je me suis demandé si quelqu'un d'autre était tombé sur ce

Edit: Vous pouvez voir de quoi je parle dans cette URL: https://github.com/facebook/flux/blob/master/examples/flux-chat/js/components/ThreadSection.react.js

Remarquez comment ThreadSection est un composant enfant, qui récupère des données directement à partir d'un magasin et les utilise comme état.

Si vous suivez la React "façon", je m'attendais à ce que l'état soit géré par le magasin - pas un composant enfant.

La solution à laquelle nous avons pensé est de récupérer tous les magasins du composant de niveau supérieur (en tant qu'accessoires) et de les transmettre aux composants enfants selon les besoins. Mais ça devient plutôt moche plutôt vite.

Nous le faisons parce que setProps ne fonctionne pas sur les composants enfants

25
Guy Nesher

Comprenez que vous devez avoir 2 types de composants. Composants avec état et composants de vue.

Les composants avec état peuvent avoir 3 types d'états: l'état initial, l'état d'entrée utilisateur et l'état du magasin de données.

Les composants avec état sont comme de petits points d'entrée dans le "widget" que vous assemblez. Il n'y a plus de point d'entrée unique à l'échelle de l'application pour la dépendance en aval ou l'injection de données, car tous ces widgets ont leur propre cycle de vie isolé. C'est pourquoi ils doivent eux-mêmes accéder et écouter les magasins.

Outre les propriétés comportementales, les composants avec état ne reçoivent pas de données réelles via les propriétés en amont.

Les composants avec état gèrent leur propre état et le transmettent à leurs enfants pour effectuer le rendu via les propriétés en aval.

Les composants avec état ne rendent normalement pas directement les éléments DOM HTML eux-mêmes. Ils ressemblent davantage aux contrôleurs de MVC et utilisent d'autres composants plus stupides, comme les vues dans MVC, pour réellement rendre les éléments DOM.

Les composants Dumber sont comme des vues, ils ne contiennent donc que la logique de rendu des éléments DOM. Considérez-les comme des modèles handlebars.js qui ne reçoivent que des propriétés, et rendez simplement ceux-ci dans des éléments DOM, éventuellement avec des boucles, etc. Ce sont des rendus sans état.

J'espère que ça répond à ta question.

43
Rygu

Selon la documentation officielle, un magasin devrait mettre à jour l'état du composant parent et le transmettre via ses accessoires enfants:

Lorsqu'il reçoit l'événement du magasin, il demande d'abord les nouvelles données dont il a besoin via les méthodes getter publiques des magasins. Il appelle ensuite ses propres méthodes setState () ou forceUpdate (), provoquant l'exécution de sa méthode render () et de la méthode render () de tous ses descendants.

Nous transmettons souvent la totalité de l'état du magasin à la chaîne de vues dans un seul objet, permettant à différents descendants d'utiliser ce dont ils ont besoin. En plus de garder le comportement de type contrôleur en haut de la hiérarchie, et donc de garder nos vues descendantes aussi purement fonctionnelles que possible, le fait de transmettre tout l'état du magasin dans un seul objet a également pour effet de réduire le nombre d'accessoires nous devons gérer.

(facebook flux docs - Présentation)

7
yarden

Il est plus logique de mettre les données du magasin dans l'état du composant, car les accessoires peuvent changer par un composant parent avec componentWillReceiveProps . Il est donc logique de mettre à jour le state chaque fois que:

  • l'événement de changement du magasin est déclenché et
  • chaque fois que les accessoires changent (en mettant les données dérivées liées uniquement au composant lui-même à l'état)

Vous trouverez ci-dessous un exemple de composant qui met à jour l'écoute d'un magasin de reflux et également des changements d'accessoires. J'utilise rarement this.props dans la fonction render, au lieu de cela je les modifie (crée des données dérivées qui ne sont utilisées que dans le composant lui-même) au fur et à mesure que de nouveaux accessoires arrivent.

var SampleComponent = React.createClass({
    mixins: [Reflux.ListenerMixin],

    // reusable helper function to build state object
    buildStateFromProps: function(props) {
        return {
            actualHeight: props.height + 20
        }
    },

    // default props if no such was set by a parent component
    getDefaultProps: function() {
        return {
            height: 100
        };
    },

    // initial state with all value set to something default
    // even using buildStateFromProps with default props
    getInitialState: function() {
        // this.props is built before this.state
        var state = buildStateFromProps(this.props);
        // append default data from store
        state.text = '';
    },

    // happens when the parent component send different 
    // props data
    componentWillReceiveProps: function(nextProps) {
        // building derivative data from new props
        // reusing buildStateFromProps
        this.setState(buildStateFromProps(nextProps));
    },

    // setting up store to be used by the component
    componentDidMount: function() {
        // this.listenTo is a helper function ListenerMixin
        this.listenTo(sampleStore, sampleUpdated);
    },

    // is called from the sampleStore update
    sampleUpdated: function(sampleData) {
        this.setState({
            text: sampleData.text
        });
    },

    render: function() {
        return (
            // ... 
            // using this.state.text from store updates and
            // this.state.height from prop updates
        );
    }
});

La raison pour laquelle j'envoie des données d'accessoires à l'état est d'éviter d'encombrer la fonction de rendu. Sinon, la fonction de rendu contiendra beaucoup de code qui n'est pas vraiment lié au "rendu" du composant. De plus, si ces données dérivées sont utilisées dans d'autres parties de l'application, il est facile de les extraire du composant et de les placer dans le magasin.

J'espère que cela t'aides.

5
Spoike

Une réponse valide à cette question se trouve cachée dans les commentaires d'une réponse précédente:

@idolize vous pouvez également passer des magasins en utilisant des contextes React (une fonctionnalité cachée, pas encore officiellement documentée). C'est vraiment bien parce que vous n'avez pas à faire tout cela en passant par la hiérarchie. sont quelques articles sur les contextes, recherchez-les en ligne! - Andy 17 juillet 15 à 18:41

1
UKM