web-dev-qa-db-fra.com

Comment le fournisseur et la connexion fonctionnent-ils dans React?

1- Provider

Pourquoi devons-nous envelopper tous nos composants dans Provider?

2- connect:

Comment connect transmet-il le magasin redux en tant que props aux composants?

3- Pouvons-nous construire nos propres Provider et connect?

Ci-dessous, un exemple React Redux simple et entièrement fonctionnel qui affiche simplement un nom dans le magasin redux et utilise React Redux connect et Provider, alors comment ConnectedComponent peut simplement accéder à this.props.name?

import React, { Component } from "react";
import { render } from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";

var defaultState = {
  name: "Amr"
};

function rootReducer(state = defaultState, action) {
  return state;
}

var store = createStore(rootReducer);


class ConnectedComp extends Component {
  render() {
    return (
        <h2>{this.props.name}</h2>
    );
  }
}
function mapStateToProps(state) {
  return {
    name: state.name
  };
}
ConnectedComp = connect(mapStateToProps)(ConnectedComp);



class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <ConnectedComp />
      </Provider>
    );
  }
}

render(<App />, document.getElementById("root"));

Un exemple pleinement fonctionnel ici https://codesandbox.io/s/lpvnxro7n7

18
Amr Labib

Pour pouvoir comprendre le fonctionnement de Provider et connect, nous devons comprendre 2 concepts dans React

1- API de contexte:

Le contexte est un moyen de transmettre des données à travers l'arborescence des composants sans avoir à passer les accessoires manuellement à chaque niveau, vous pouvez en savoir plus sur contexte ici

2- Composant d'ordre supérieur (HOC):

Un composant d'ordre supérieur est une fonction qui prend un composant et retourne un nouveau composant, mais avant de retourner le nouveau composant, vous pouvez passer des accessoires personnalisés supplémentaires puis le renvoyer, vous pouvez en savoir plus sur HOC ici


3- Construisez nos propres Provider et connect

Maintenant que nous comprenons à la fois le contexte et le composant d'ordre supérieur, nous les utiliserons pour créer le même exemple pleinement fonctionnel dans la question, mais en utilisant nos propres myProvider et myConnect


MyProvider

//This is how we utilize React Context and create MyProvider component that will pass store to all its child components automatically
//This is also known by Provider pattern
class MyProvider extends Component {
  //By adding the getChildContext function and childContextTypes, React passes the information down automatically to any component in the subtree
  getChildContext() {
    const { store } = this.props
    return { store }
  }

  render() {
    return this.props.children;
  }
}

MyProvider.childContextTypes = {
  store: PropTypes.object.isRequired,
}

myConnect

//This is the Higher Order Component
function myConnect(mapStateToPropsFunc) {
  return function (WrappedComp) {
    var myHOC = class HOC extends Component {
      render() {
        //Now we access redux store using react context api as it will be passed by MyProvider automatically to all child components
        var myStore = this.context.store.getState();
        //mapStateToPropsFunc is just used to structure the props required by the component so we pass to mapStateToPropsFunc the whole store and then it returns a mapped object with required props thats why it is well known by mapStateToProps
        var storeToBePassed = mapStateToPropsFunc(myStore);
        return (
          //We pass the result from executing mapStateToPropsFunc to the wrapped component and this is how the components get passed props from redux store
          <WrappedComp {...storeToBePassed} />
        )
      }
    }

    //We need to define contextTypes otherwise context will be empty
    myHOC.contextTypes = {
      store: PropTypes.object
    };

    //return new component that has access to redux store as props mapped using mapStateToProps function
    return myHOC;
  }
}

Le même exemple simple utilisant nos propres MyProvider et myConnect

//Note that we removed react-redux library
import React, { Component, Children } from "react";
import { PropTypes } from "prop-types";
import { render } from "react-dom";
import { createStore } from "redux";

var defaultState = {
  name: "Amr"
};

function rootReducer(state = defaultState, action) {
  return state;
}

var store = createStore(rootReducer);

class App extends Component {
  render() {
    //Here we use our own built myProvider and pass store
    return (
      <MyProvider store={store}>
        <ConnectedComp />
      </MyProvider>
    );
  }
}

class ConnectedComp extends Component {
  render() {
    return (
      <h2>{this.props.name}</h2>
    );
  }
}

//mapStateToProps is a normal function that get store as parameter and return the required props by that component, btw this function can have any name
function mapStateToProps(state) {
  return {
    name: state.name
  };
}

//Here we use our own built myConnect
ConnectedComp = myConnect(mapStateToProps)(ConnectedComp);

render(<App />, document.getElementById("root"));

Vous pouvez tester l'implémentation ci-dessus ici https://codesandbox.io/s/727pl0mqoq


Cet exemple est une illustration simple de la façon dont react-redux Provider et connect peut être construit en utilisant à la fois React Context et HOC.

Cela nous permet de mieux comprendre pourquoi nous utilisons Provider, connect et mapStateToProps

27
Amr Labib