web-dev-qa-db-fra.com

Redux, Dois-je importer un magasin dans tous mes conteneurs si je veux avoir accès aux données?

Peut-être que je ne pense pas à redux, mais tous les exemples que j'ai vus n'accèdent pas trop à l'état entre les conteneurs et je n'ai donc pas vu beaucoup d'utilisation de store.getState (), mais même si vous voulez envoi, vous devez avoir accès à stocker, non?

Donc, autre que l'importation du magasin d'importation depuis 'chemin/vers/magasin/magasin'

dans chaque fichier que je veux obtenir, ou "dispatch", comment puis-je accéder à cet état, car si je ne l'inclus pas, store n'est pas défini.

52
james emanon

En règle générale, vous souhaitez définir uniquement les composants de conteneur de niveau supérieur ayant accès au magasin. Ils transmettent toutes les données nécessaires ou les actions à transmettre en tant que supports aux composants enfants. C'est la différence entre un composant "intelligent" et un composant "stupide" - les composants "intelligents" connaissent le magasin/l'état Redux, alors que les composants "stupides" ne font que leur transmettre des accessoires et n'ont aucune idée du plus grand état de l'application.

Cependant, le simple fait de passer du magasin aux composants du conteneur peut devenir fastidieux. C'est pourquoi React-Redux fournit un composant prêt à l'emploi qui enveloppe l'ensemble de votre application. Check it out dans la documentation. Ceci est le composant Provider et lorsque vous enveloppez votre application dans son intégralité, vous ne transmettez le magasin qu'à un composant une fois:

import createStore from '../store';

const store = createStore()

class App extends Component {

  render() {
    return (
      <Provider store={store}>
        <MainAppContainer />
      </Provider>
    )
  }
}

Comme vous pouvez le voir ici, j'ai un fichier de configuration séparé juste pour mon magasin car il y a beaucoup de modifications que vous pouvez faire et pour toute application distante complexe, vous vous retrouverez à faire de même pour des choses comme utiliser compose appliquer le middleware.

Ensuite, l’un des composants "intelligents" restants (généralement des wrappers) doit écouter le magasin. Ceci est accompli en utilisant la méthode connect . Cela vous permet de mapper des parties de l'état sur les propriétés de votre composant, ainsi que des actions de répartition en tant que propriétés.

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from './actionCreators';

const mapStateToProps = function(state){
  return {
    something: state.something,
  }
}

const mapDispatchToProps = function (dispatch) {
  return bindActionCreators({
    getSomething: actionCreators.getSomething,
  }, dispatch)
}

class MainAppContainer extends Component {

    componentDidMount() {
      //now has access to data like this.props.something, which is from store
      //now has access to dispatch actions like this.props.getSomething
    }

    render() {
        //will pass down store data and dispatch actions to child components
        return (
               <div>
                   <ChildComponent1 something={this.props.something} />
                   <ChildComponent2 getSomething={this.props.getSomething} />
               </div>
        )
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MainAppContainer)

Comme vous transmettez toujours les actions et les données de répartition à votre composant enfants en tant que propriétés, vous référencez celles-ci sur ce composant avec this.props.

En vous basant sur l'exemple ci-dessus, vous verrez que parce que j'ai passé this.props.something à ChildComponent1, il a accès aux données something du magasin mais n’a pas accès à l’action de dispatch getSomething. Également, ChildComponent2 n'a accès qu'à l'action de dispatch getSomething mais pas aux données something. Cela signifie que vous exposez uniquement les composants à ce dont ils ont besoin dans le magasin.

Par exemple, parce que ChildComponent2 _ a été transmis l'action de dispatch comme getSomething, dans mon onClick je peux appeler this.props.getSomething et il appellera l’action dispatch sans aucun accès au magasin. De la même manière, il peut continuer à transmettre getSomething à un autre composant enfant et ce composant peut l'appeler et/ou le transmettre et le cycle peut se poursuivre indéfiniment.

class ChildComponent2 extends Component {

    render() {
        return (
            <div>
                <div onClick={this.props.getSomething}>Click me</div>
                <NestedComponent getSomething={this.props.getSomething} />
            </div>
        )
    }
}

Editer à partir des commentaires

Bien que cela ne concerne pas directement la question, dans les commentaires, vous sembliez un peu confus à propos des actions. Je n'ai pas défini l'action getSomething ici. Au lieu de cela, il est habituel dans les applications Redux de placer toutes vos définitions d’action dans un fichier séparé appelé actionCreators.js. Cela contient des fonctions qui portent le même nom que vos actions et renvoient un objet avec une propriété type et toutes les autres méthodes/données requises par cette action. Par exemple, voici un exemple très simple actionCreators.js fichier:

export function getSomething() {
    return {
        type: 'GET_SOMETHING',
        payload: {
            something: 'Here is some data'
        }
    }
}

Ce type d'action correspond à ce que votre réducteur écoute pour savoir quelle action est déclenchée.

80
Andy Noelker

Si vous utilisez le react-redux package, vous finirez par envelopper vos composants dans un Provider avec un store prop. Cela configure votre magasin unique dans un contexte React, auquel on accède ensuite à partir de la méthode connect dans les composants enfants. La méthode connect prend deux fonctions (mapStateToProps. et mapDispatchToProps), qui sont vos points d'ancrage pour obtenir l'état du magasin et la distribution des messages.

jetez un oeil ici pour plus d'informations

15
Gabriel Isenberg